diff --git a/.signature b/.signature new file mode 100644 index 0000000..0ddcdf4 --- /dev/null +++ b/.signature @@ -0,0 +1 @@ +{"timestamp":1734331212,"signature":"mMrBXdBegYd6TPqNVci9OkWh1H10YU8Ug8KlSpiyNzbXlS5z7O7Rdif3gvTdXK0O07HWmIuszcUoljQIaxkGAYq2g9A85IcvhbWsAAqxjSEZfQPsxFZlJQ9PqU4tfMItk7K1VP1YfcBxitxPHcUeO2IwBYVLx51gg6X/0qHWtkifmZ/cBbGTBNEYE+m7KfRYUyu23kOPMGOCBeULivZO9y/2A0qXkMeBiPo3KQFU6481n4GV6fahyLrG2llfM8xtW8YeouPyt/IMD86at8eeY+E5mW0iXGms9IMLf/DH6vjJnuSEfgMXfjcGnRO0m+RP+ig8HzjbPVty7oAOgfm6Oc1frOP4Cmudk97fIEzC10B0lj2uzFudT5UVPk4Hr6Mf/2ka0m+XTdRNHVRyOYBcHsJQYf0HKW/4jJPwWrSCSk2uE0fPn1sTvMb+i4pXCn7J700b7NMLPFJaWeb6kA2e3v8w5FybshFZWCU6fyLWGn1AR60u0BxL88Hx4VO5UjnJ","publicKey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3423d9a..e6930d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). + +## [2.2.0] - 2024-12-12 + +### Added + +- Added `NetworkObject.OwnershipStatus.SessionOwner` to allow Network Objects to be distributable and only owned by the Session Owner. This flag will override all other `OwnershipStatus` flags. (#3175) +- Added `UnityTransport.GetEndpoint` method to provide a way to obtain `NetworkEndpoint` information of a connection via client identifier. (#3130) +- Added `NetworkTransport.OnEarlyUpdate` and `NetworkTransport.OnPostLateUpdate` methods to provide more control over handling transport related events at the start and end of each frame. (#3113) + +### Fixed + +- Fixed issue where the server, host, or session owner would not populate the in-scene place `NetworkObject` table if the scene was loaded prior to starting the `NetworkManager`. (#3177) +- Fixed issue where the `NetworkObjectIdHash` value could be incorrect when entering play mode while still in prefab edit mode with pending changes and using MPPM. (#3162) +- Fixed issue where a sever only `NetworkManager` instance would spawn the actual `NetworkPrefab`'s `GameObject` as opposed to creating an instance of it. (#3160) +- Fixed issue where only the session owner (as opposed to all clients) would handle spawning prefab overrides properly when using a distributed authority network topology. (#3160) +- Fixed issue where an exception was thrown when calling `NetworkManager.Shutdown` after calling `UnityTransport.Shutdown`. (#3118) +- Fixed issue where `NetworkList` properties on in-scene placed `NetworkObject`s could cause small memory leaks when entering playmode. (#3147) +- Fixed in-scene `NertworkObject` synchronization issue when loading a scene with currently connected clients connected to a session created by a `NetworkManager` started as a server (i.e. not as a host). (#3133) +- Fixed issue where a `NetworkManager` started as a server would not add itself as an observer to in-scene placed `NetworkObject`s instantiated and spawned by a scene loading event. (#3133) +- Fixed issue where spawning a player using `NetworkObject.InstantiateAndSpawn` or `NetworkSpawnManager.InstantiateAndSpawn` would not update the `NetworkSpawnManager.PlayerObjects` or assign the newly spawned player to the `NetworkClient.PlayerObject`. (#3122) +- Fixed issue where queued UnitTransport (NetworkTransport) message batches were being sent on the next frame. They are now sent at the end of the frame during `PostLateUpdate`. (#3113) +- Fixed issue where `NotOwnerRpcTarget` or `OwnerRpcTarget` were not using their replacements `NotAuthorityRpcTarget` and `AuthorityRpcTarget` which would invoke a warning. (#3111) +- Fixed issue where client is removed as an observer from spawned objects when their player instance is despawned. (#3110) +- Fixed issue where `NetworkAnimator` would statically allocate write buffer space for `Animator` parameters that could cause a write error if the number of parameters exceeded the space allocated. (#3108) + +### Changed + +- In-scene placed `NetworkObject`s have been made distributable when balancing object distribution after a connection event. (#3175) +- Optimised `NetworkVariable` and `NetworkTransform` related packets when in Distributed Authority mode. +- The Debug Simulator section of the Unity Transport component was removed. This section was not functional anymore and users are now recommended to use the more featureful [Network Simulator](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/) tool from the Multiplayer Tools package instead. (#3121) + ## [2.1.1] - 2024-10-18 ### Added @@ -187,8 +218,8 @@ Additional documentation and release notes are available at [Multiplayer Documen ## [2.0.0-exp.2] - 2024-04-02 ### Added -- Added updates to all internal messages to account for a distributed authority network session connection. (#2863) -- Added `NetworkRigidbodyBase` that provides users with a more customizable network rigidbody, handles both `Rigidbody` and `Rigidbody2D`, and provides an option to make `NetworkTransform` use the rigid body for motion. (#2863) +- Added updates to all internal messages to account for a distributed authority network session connection. (#2863) +- Added `NetworkRigidbodyBase` that provides users with a more customizable network rigidbody, handles both `Rigidbody` and `Rigidbody2D`, and provides an option to make `NetworkTransform` use the rigid body for motion. (#2863) - For a customized `NetworkRigidbodyBase` class: - `NetworkRigidbodyBase.AutoUpdateKinematicState` provides control on whether the kinematic setting will be automatically set or not when ownership changes. - `NetworkRigidbodyBase.AutoSetKinematicOnDespawn` provides control on whether isKinematic will automatically be set to true when the associated `NetworkObject` is despawned. @@ -324,6 +355,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed issue where you could not have multiple source network prefab overrides targeting the same network prefab as their override. (#2710) ### Changed + - Changed the server or host shutdown so it will now perform a "soft shutdown" when `NetworkManager.Shutdown` is invoked. This will send a disconnect notification to all connected clients and the server-host will wait for all connected clients to disconnect or timeout after a 5 second period before completing the shutdown process. (#2789) - Changed `OnClientDisconnectedCallback` will now return the assigned client identifier on the local client side if the client was approved and assigned one prior to being disconnected. (#2789) - Changed `NetworkTransform.SetState` (and related methods) now are cumulative during a fractional tick period and sent on the next pending tick. (#2777) @@ -336,6 +368,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Changed in-scene placed `NetworkObject`s now set their `IsSceneObject` value when generating their `GlobalObjectIdHash` value. (#2710) - Changed the default `NetworkConfig.SpawnTimeout` value from 1.0s to 10.0s. (#2710) + ## [1.7.1] - 2023-11-15 ### Added @@ -385,7 +418,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added - Added a protected virtual method `NetworkTransform.OnInitialize(ref NetworkTransformState replicatedState)` that just returns the replicated state reference. - + ### Fixed - Fixed issue where invoking `NetworkManager.Shutdown` within `NetworkManager.OnClientStopped` or `NetworkManager.OnServerStopped` would force `NetworkManager.ShutdownInProgress` to remain true after completing the shutdown process. (#2661) @@ -443,7 +476,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed issue where invalid endpoint addresses were not being detected and returning false from NGO UnityTransport. (#2496) - Fixed some errors that could occur if a connection is lost and the loss is detected when attempting to write to the socket. (#2495) -## Changed +### Changed - Adding network prefabs before NetworkManager initialization is now supported. (#2565) - Connecting clients being synchronized now switch to the server's active scene before spawning and synchronizing NetworkObjects. (#2532) diff --git a/Editor/NetworkManagerEditor.cs b/Editor/NetworkManagerEditor.cs index 0684d74..8ba4128 100644 --- a/Editor/NetworkManagerEditor.cs +++ b/Editor/NetworkManagerEditor.cs @@ -237,7 +237,7 @@ namespace Unity.Netcode.Editor if (m_NetworkManager.NetworkConfig.NetworkTopology == NetworkTopologyTypes.DistributedAuthority) { EditorGUILayout.PropertyField(m_AutoSpawnPlayerPrefabClientSide, new GUIContent("Auto Spawn Player Prefab")); - } + } #endif EditorGUILayout.PropertyField(m_PlayerPrefabProperty, new GUIContent("Default Player Prefab")); diff --git a/Editor/NetworkObjectEditor.cs b/Editor/NetworkObjectEditor.cs index ef6ea58..0860fd9 100644 --- a/Editor/NetworkObjectEditor.cs +++ b/Editor/NetworkObjectEditor.cs @@ -88,6 +88,14 @@ namespace Unity.Netcode.Editor while (observerClientIds.MoveNext()) { + if (!m_NetworkObject.NetworkManager.ConnectedClients.ContainsKey(observerClientIds.Current)) + { + if ((observerClientIds.Current == 0 && m_NetworkObject.NetworkManager.IsHost) || observerClientIds.Current > 0) + { + Debug.LogWarning($"Client-{observerClientIds.Current} is listed as an observer but is not connected!"); + } + continue; + } if (m_NetworkObject.NetworkManager.ConnectedClients[observerClientIds.Current].PlayerObject != null) { EditorGUILayout.ObjectField($"ClientId: {observerClientIds.Current}", m_NetworkObject.NetworkManager.ConnectedClients[observerClientIds.Current].PlayerObject, typeof(GameObject), false); @@ -107,6 +115,10 @@ namespace Unity.Netcode.Editor EditorGUI.BeginChangeCheck(); serializedObject.UpdateIfRequiredOrScript(); DrawPropertiesExcluding(serializedObject, k_HiddenFields); + if (m_NetworkObject.IsOwnershipSessionOwner) + { + m_NetworkObject.Ownership = NetworkObject.OwnershipStatus.SessionOwner; + } serializedObject.ApplyModifiedProperties(); EditorGUI.EndChangeCheck(); @@ -185,9 +197,9 @@ namespace Unity.Netcode.Editor // The below can cause visual anomalies and/or throws an exception within the EditorGUI itself (index out of bounds of the array). and has // The visual anomaly is when you select one field it is set in the drop down but then the flags selection in the popup menu selects more items - // even though if you exit the popup menu the flag setting is correct. - //var ownership = (NetworkObject.OwnershipStatus)EditorGUI.EnumFlagsField(position, label, (NetworkObject.OwnershipStatus)property.enumValueFlag); - //property.enumValueFlag = (int)ownership; + // even though if you exit the popup menu the flag setting is correct. + // var ownership = (NetworkObject.OwnershipStatus)EditorGUI.EnumFlagsField(position, label, (NetworkObject.OwnershipStatus)property.enumValueFlag); + // property.enumValueFlag = (int)ownership; EditorGUI.EndDisabledGroup(); EditorGUI.EndProperty(); } diff --git a/Editor/com.unity.netcode.editor.asmdef b/Editor/com.unity.netcode.editor.asmdef index e80328c..e5116ec 100644 --- a/Editor/com.unity.netcode.editor.asmdef +++ b/Editor/com.unity.netcode.editor.asmdef @@ -34,16 +34,6 @@ "expression": "", "define": "COM_UNITY_MODULES_ANIMATION" }, - { - "name": "com.unity.modules.physics", - "expression": "", - "define": "COM_UNITY_MODULES_PHYSICS" - }, - { - "name": "com.unity.modules.physics2d", - "expression": "", - "define": "COM_UNITY_MODULES_PHYSICS2D" - }, { "name": "com.unity.services.relay", "expression": "1.0", diff --git a/LICENSE.md b/LICENSE.md index 031978c..ee8cecf 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,5 @@ Unity Companion License (UCL License) -com.unity.netcode.gameobjects copyright © 2021-2024 Unity Technologies +com.unity.netcode.gameobjects copyright © 2024 Unity Technologies Licensed under the Unity Companion License for Unity-dependent projects (see https://unity3d.com/legal/licenses/unity_companion_license). Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. - - diff --git a/Runtime/Components/AnticipatedNetworkTransform.cs b/Runtime/Components/AnticipatedNetworkTransform.cs deleted file mode 100644 index d490422..0000000 --- a/Runtime/Components/AnticipatedNetworkTransform.cs +++ /dev/null @@ -1,543 +0,0 @@ -using Unity.Mathematics; -using UnityEngine; - -namespace Unity.Netcode.Components -{ - -#pragma warning disable IDE0001 - /// - /// A subclass of that supports basic client anticipation - the client - /// can set a value on the belief that the server will update it to reflect the same value in a future update - /// (i.e., as the result of an RPC call). This value can then be adjusted as new updates from the server come in, - /// in three basic modes: - /// - /// - /// - /// Snap: In this mode (with set to - /// and no callback), - /// the moment a more up-to-date value is received from the authority, it will simply replace the anticipated value, - /// resulting in a "snap" to the new value if it is different from the anticipated value. - /// - /// Smooth: In this mode (with set to - /// and an callback that calls - /// from the anticipated value to the authority value with an appropriate - /// -style smooth function), when a more up-to-date value is received from the authority, - /// it will interpolate over time from an incorrect anticipated value to the correct authoritative value. - /// - /// Constant Reanticipation: In this mode (with set to - /// and an that calculates a - /// new anticipated value based on the current authoritative value), when a more up-to-date value is received from - /// the authority, user code calculates a new anticipated value, possibly calling to interpolate - /// between the previous anticipation and the new anticipation. This is useful for values that change frequently and - /// need to constantly be re-evaluated, as opposed to values that change only in response to user action and simply - /// need a one-time anticipation when the user performs that action. - /// - /// - /// - /// Note that these three modes may be combined. For example, if an callback - /// does not call either or one of the Anticipate methods, the result will be a snap to the - /// authoritative value, enabling for a callback that may conditionally call when the - /// difference between the anticipated and authoritative values is within some threshold, but fall back to - /// snap behavior if the difference is too large. - /// -#pragma warning restore IDE0001 - [DisallowMultipleComponent] - [AddComponentMenu("Netcode/Anticipated Network Transform")] - public class AnticipatedNetworkTransform : NetworkTransform - { - -#if UNITY_EDITOR - internal override bool HideInterpolateValue => true; -#endif - - public struct TransformState - { - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Scale; - } - - private TransformState m_AuthoritativeTransform = new TransformState(); - private TransformState m_AnticipatedTransform = new TransformState(); - private TransformState m_PreviousAnticipatedTransform = new TransformState(); - private ulong m_LastAnticipaionCounter; - private ulong m_LastAuthorityUpdateCounter; - - private TransformState m_SmoothFrom; - private TransformState m_SmoothTo; - private float m_SmoothDuration; - private float m_CurrentSmoothTime; - - private bool m_OutstandingAuthorityChange = false; - -#if UNITY_EDITOR - private void Reset() - { - // Anticipation + smoothing is a form of interpolation, and adding NetworkTransform's buffered interpolation - // makes the anticipation get weird, so we default it to false. - Interpolate = false; - } -#endif - -#pragma warning disable IDE0001 - /// - /// Defines what the behavior should be if we receive a value from the server with an earlier associated - /// time value than the anticipation time value. - ///

- /// If this is , the stale data will be ignored and the authoritative - /// value will not replace the anticipated value until the anticipation time is reached. - /// and will also not be invoked for this stale data. - ///

- /// If this is , the stale data will replace the anticipated data and - /// and will be invoked. - /// In this case, the authoritativeTime value passed to will be lower than - /// the anticipationTime value, and that callback can be used to calculate a new anticipated value. - ///
-#pragma warning restore IDE0001 - public StaleDataHandling StaleDataHandling = StaleDataHandling.Reanticipate; - - /// - /// Contains the current state of this transform on the server side. - /// Note that, on the server side, this gets updated at the end of the frame, and will not immediately reflect - /// changes to the transform. - /// - public TransformState AuthoritativeState => m_AuthoritativeTransform; - - /// - /// Contains the current anticipated state, which will match the values of this object's - /// actual . When a server - /// update arrives, this value will be overwritten by the new - /// server value (unless stale data handling is set to "Ignore" - /// and the update is determined to be stale). This value will - /// be duplicated in , which - /// will NOT be overwritten in server updates. - /// - public TransformState AnticipatedState => m_AnticipatedTransform; - - /// - /// Indicates whether this transform currently needs - /// reanticipation. If this is true, the anticipated value - /// has been overwritten by the authoritative value from the - /// server; the previous anticipated value is stored in - /// - public bool ShouldReanticipate - { - get; - private set; - } - - /// - /// Holds the most recent anticipated state, whatever was - /// most recently set using the Anticipate methods. Unlike - /// , this does not get overwritten - /// when a server update arrives. - /// - public TransformState PreviousAnticipatedState => m_PreviousAnticipatedTransform; - - /// - /// Anticipate that, at the end of one round trip to the server, this transform will be in the given - /// - /// - /// - public void AnticipateMove(Vector3 newPosition) - { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) - { - return; - } - transform.position = newPosition; - m_AnticipatedTransform.Position = newPosition; - if (CanCommitToTransform) - { - m_AuthoritativeTransform.Position = newPosition; - } - - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - } - - /// - /// Anticipate that, at the end of one round trip to the server, this transform will have the given - /// - /// - /// - public void AnticipateRotate(Quaternion newRotation) - { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) - { - return; - } - transform.rotation = newRotation; - m_AnticipatedTransform.Rotation = newRotation; - if (CanCommitToTransform) - { - m_AuthoritativeTransform.Rotation = newRotation; - } - - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - } - - /// - /// Anticipate that, at the end of one round trip to the server, this transform will have the given - /// - /// - /// - public void AnticipateScale(Vector3 newScale) - { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) - { - return; - } - transform.localScale = newScale; - m_AnticipatedTransform.Scale = newScale; - if (CanCommitToTransform) - { - m_AuthoritativeTransform.Scale = newScale; - } - - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - } - - /// - /// Anticipate that, at the end of one round trip to the server, the transform will have the given - /// - /// - /// - public void AnticipateState(TransformState newState) - { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) - { - return; - } - var transform_ = transform; - transform_.position = newState.Position; - transform_.rotation = newState.Rotation; - transform_.localScale = newState.Scale; - m_AnticipatedTransform = newState; - if (CanCommitToTransform) - { - m_AuthoritativeTransform = newState; - } - - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - } - - private void ProcessSmoothing() - { - // If not spawned or this instance has authority, exit early - if (!IsSpawned) - { - return; - } - - if (m_CurrentSmoothTime < m_SmoothDuration) - { - m_CurrentSmoothTime += NetworkManager.RealTimeProvider.DeltaTime; - var transform_ = transform; - var pct = math.min(m_CurrentSmoothTime / m_SmoothDuration, 1f); - - m_AnticipatedTransform = new TransformState - { - Position = Vector3.Lerp(m_SmoothFrom.Position, m_SmoothTo.Position, pct), - Rotation = Quaternion.Lerp(m_SmoothFrom.Rotation, m_SmoothTo.Rotation, pct), - Scale = Vector3.Lerp(m_SmoothFrom.Scale, m_SmoothTo.Scale, pct) - }; - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - if (!CanCommitToTransform) - { - transform_.position = m_AnticipatedTransform.Position; - transform_.localScale = m_AnticipatedTransform.Scale; - transform_.rotation = m_AnticipatedTransform.Rotation; - } - } - } - - // TODO: This does not handle OnFixedUpdate - // This requires a complete overhaul in this class to switch between using - // NetworkRigidbody's position and rotation values. - public override void OnUpdate() - { - ProcessSmoothing(); - // Do not call the base class implementation... - // AnticipatedNetworkTransform applies its authoritative state immediately rather than waiting for update - // This is because AnticipatedNetworkTransforms may need to reference each other in reanticipating - // and we will want all reanticipation done before anything else wants to reference the transform in - // OnUpdate() - //base.OnUpdate(); - } - - /// - /// Since authority does not subscribe to updates (OnUpdate or OnFixedUpdate), - /// we have to update every frame to assure authority processes soothing. - /// - private void Update() - { - if (CanCommitToTransform && IsSpawned) - { - ProcessSmoothing(); - } - } - - internal class AnticipatedObject : IAnticipationEventReceiver, IAnticipatedObject - { - public AnticipatedNetworkTransform Transform; - - - public void SetupForRender() - { - if (Transform.CanCommitToTransform) - { - var transform_ = Transform.transform; - Transform.m_AuthoritativeTransform = new TransformState - { - Position = transform_.position, - Rotation = transform_.rotation, - Scale = transform_.localScale - }; - if (Transform.m_CurrentSmoothTime >= Transform.m_SmoothDuration) - { - // If we've had a call to Smooth() we'll continue interpolating. - // Otherwise we'll go ahead and make the visual and actual locations - // match. - Transform.m_AnticipatedTransform = Transform.m_AuthoritativeTransform; - } - - transform_.position = Transform.m_AnticipatedTransform.Position; - transform_.rotation = Transform.m_AnticipatedTransform.Rotation; - transform_.localScale = Transform.m_AnticipatedTransform.Scale; - } - } - - public void SetupForUpdate() - { - if (Transform.CanCommitToTransform) - { - var transform_ = Transform.transform; - transform_.position = Transform.m_AuthoritativeTransform.Position; - transform_.rotation = Transform.m_AuthoritativeTransform.Rotation; - transform_.localScale = Transform.m_AuthoritativeTransform.Scale; - } - } - - public void Update() - { - // No need to do this, it's handled by NetworkTransform.OnUpdate - } - - public void ResetAnticipation() - { - Transform.ShouldReanticipate = false; - } - - public NetworkObject OwnerObject => Transform.NetworkObject; - } - - private AnticipatedObject m_AnticipatedObject = null; - - private void ResetAnticipatedState() - { - var transform_ = transform; - m_AuthoritativeTransform = new TransformState - { - Position = transform_.position, - Rotation = transform_.rotation, - Scale = transform_.localScale - }; - m_AnticipatedTransform = m_AuthoritativeTransform; - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - } - - /// - /// (This replaces the first OnSynchronize for NetworkTransforms) - /// This is needed to initialize when fully synchronized since non-authority instances - /// don't apply the initial synchronization (new client synchronization) until after - /// everything has been spawned and synchronized. - /// - protected internal override void InternalOnNetworkSessionSynchronized() - { - var wasSynchronizing = SynchronizeState.IsSynchronizing; - base.InternalOnNetworkSessionSynchronized(); - if (!CanCommitToTransform && wasSynchronizing && !SynchronizeState.IsSynchronizing) - { - m_OutstandingAuthorityChange = true; - ApplyAuthoritativeState(); - ResetAnticipatedState(); - - m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); - } - } - - /// - /// (This replaces the any subsequent OnSynchronize for NetworkTransforms post client synchronization) - /// This occurs on already connected clients when dynamically spawning a NetworkObject for - /// non-authoritative instances. - /// - protected internal override void InternalOnNetworkPostSpawn() - { - base.InternalOnNetworkPostSpawn(); - if (!CanCommitToTransform && NetworkManager.IsConnectedClient && !SynchronizeState.IsSynchronizing) - { - m_OutstandingAuthorityChange = true; - ApplyAuthoritativeState(); - ResetAnticipatedState(); - m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); - } - } - - public override void OnNetworkSpawn() - { - if (NetworkManager.DistributedAuthorityMode) - { - Debug.LogWarning($"This component is not currently supported in distributed authority."); - } - base.OnNetworkSpawn(); - - // Non-authoritative instances exit early if the synchronization has yet to - // be applied at this point - if (SynchronizeState.IsSynchronizing && !CanCommitToTransform) - { - return; - } - m_OutstandingAuthorityChange = true; - ApplyAuthoritativeState(); - ResetAnticipatedState(); - - m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); - } - - public override void OnNetworkDespawn() - { - if (m_AnticipatedObject != null) - { - NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); - m_AnticipatedObject = null; - } - ResetAnticipatedState(); - - base.OnNetworkDespawn(); - } - - public override void OnDestroy() - { - if (m_AnticipatedObject != null) - { - NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); - m_AnticipatedObject = null; - } - - base.OnDestroy(); - } - - /// - /// Interpolate between the transform represented by to the transform represented by - /// over of real time. The duration uses - /// , so it is affected by . - /// - /// - /// - /// - public void Smooth(TransformState from, TransformState to, float durationSeconds) - { - var transform_ = transform; - if (durationSeconds <= 0) - { - m_AnticipatedTransform = to; - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - transform_.position = to.Position; - transform_.rotation = to.Rotation; - transform_.localScale = to.Scale; - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - return; - } - m_AnticipatedTransform = from; - m_PreviousAnticipatedTransform = m_AnticipatedTransform; - - m_SmoothFrom = from; - m_SmoothTo = to; - m_SmoothDuration = durationSeconds; - m_CurrentSmoothTime = 0; - } - - protected override void OnBeforeUpdateTransformState() - { - // this is called when new data comes from the server - m_LastAuthorityUpdateCounter = NetworkManager.AnticipationSystem.LastAnticipationAck; - m_OutstandingAuthorityChange = true; - } - - protected override void OnNetworkTransformStateUpdated(ref NetworkTransformState oldState, ref NetworkTransformState newState) - { - base.OnNetworkTransformStateUpdated(ref oldState, ref newState); - ApplyAuthoritativeState(); - } - - protected override void OnTransformUpdated() - { - if (CanCommitToTransform || m_AnticipatedObject == null) - { - return; - } - // this is called pretty much every frame and will change the transform - // If we've overridden the transform with an anticipated state, we need to be able to change it back - // to the anticipated state (while updating the authority state accordingly) or else - // mark this transform for reanticipation - var transform_ = transform; - - // Update authority state to catch any possible interpolation data - m_AuthoritativeTransform.Position = transform_.position; - m_AuthoritativeTransform.Rotation = transform_.rotation; - m_AuthoritativeTransform.Scale = transform_.localScale; - - if (!m_OutstandingAuthorityChange) - { - // Keep the anticipated value unchanged, we have no updates from the server at all. - return; - } - - if (StaleDataHandling == StaleDataHandling.Ignore && m_LastAnticipaionCounter > m_LastAuthorityUpdateCounter) - { - // Keep the anticipated value unchanged because it is more recent than the authoritative one. - return; - } - - m_SmoothDuration = 0; - m_CurrentSmoothTime = 0; - m_OutstandingAuthorityChange = false; - m_AnticipatedTransform = m_AuthoritativeTransform; - - ShouldReanticipate = true; - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Add(m_AnticipatedObject); - } - } -} diff --git a/Runtime/Components/AnticipatedNetworkTransform.cs.meta b/Runtime/Components/AnticipatedNetworkTransform.cs.meta deleted file mode 100644 index bb48f93..0000000 --- a/Runtime/Components/AnticipatedNetworkTransform.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 5abfce83aadd948498d4990c645a017b \ No newline at end of file diff --git a/Runtime/Components/NetworkAnimator.cs b/Runtime/Components/NetworkAnimator.cs index 16b77ca..583e7bd 100644 --- a/Runtime/Components/NetworkAnimator.cs +++ b/Runtime/Components/NetworkAnimator.cs @@ -230,6 +230,7 @@ namespace Unity.Netcode.Components } } + #if UNITY_EDITOR private void ParseStateMachineStates(int layerIndex, ref AnimatorController animatorController, ref AnimatorStateMachine stateMachine) { @@ -263,7 +264,6 @@ namespace Unity.Netcode.Components { case AnimatorControllerParameterType.Trigger: { - if (transition.destinationStateMachine != null) { var destinationStateMachine = transition.destinationStateMachine; @@ -297,18 +297,12 @@ namespace Unity.Netcode.Components } } } -#endif /// /// Creates the TransitionStateInfoList table /// private void BuildTransitionStateInfoList() { -#if UNITY_EDITOR - if (UnityEditor.EditorApplication.isUpdating || UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) - { - return; - } if (m_Animator == null) { return; @@ -326,9 +320,18 @@ namespace Unity.Netcode.Components var stateMachine = animatorController.layers[x].stateMachine; ParseStateMachineStates(x, ref animatorController, ref stateMachine); } -#endif } + /// + /// In-Editor Only + /// Virtual OnValidate method for custom derived NetworkAnimator classes. + /// + protected virtual void OnValidate() + { + BuildTransitionStateInfoList(); + } +#endif + public void OnAfterDeserialize() { BuildDestinationToTransitionInfoTable(); @@ -336,7 +339,7 @@ namespace Unity.Netcode.Components public void OnBeforeSerialize() { - BuildTransitionStateInfoList(); + // Do nothing when serializing (handled during OnValidate) } internal struct AnimationState : INetworkSerializable @@ -419,8 +422,8 @@ namespace Unity.Netcode.Components internal bool HasBeenProcessed; // This is preallocated/populated in OnNetworkSpawn for all instances in the event ownership or - // authority changes. When serializing, IsDirtyCount determines how many AnimationState entries - // should be serialized from the list. When deserializing the list is created and populated with + // authority changes. When serializing, IsDirtyCount determines how many AnimationState entries + // should be serialized from the list. When deserializing the list is created and populated with // only the number of AnimationStates received which is dictated by the deserialized IsDirtyCount. internal List AnimationStates; @@ -496,7 +499,7 @@ namespace Unity.Netcode.Components } /// - /// Override this method and return false to switch to owner authoritative mode + /// Override this method and return false to switch to owner authoritative mode. /// /// /// When using a distributed authority network topology, this will default to @@ -507,10 +510,6 @@ namespace Unity.Netcode.Components return NetworkManager ? !NetworkManager.DistributedAuthorityMode : true; } - // Animators only support up to 32 parameters - // TODO: Look into making this a range limited property - private const int k_MaxAnimationParams = 32; - private int[] m_TransitionHash; private int[] m_AnimationHash; private float[] m_LayerWeights; @@ -534,7 +533,7 @@ namespace Unity.Netcode.Components } // 128 bytes per Animator - private FastBufferWriter m_ParameterWriter = new FastBufferWriter(k_MaxAnimationParams * sizeof(float), Allocator.Persistent); + private FastBufferWriter m_ParameterWriter; private NativeArray m_CachedAnimatorParameters; @@ -586,6 +585,14 @@ namespace Unity.Netcode.Components protected virtual void Awake() { + if (!m_Animator) + { +#if !UNITY_EDITOR + Debug.LogError($"{nameof(NetworkAnimator)} {name} does not have an {nameof(UnityEngine.Animator)} assigned to it. The {nameof(NetworkAnimator)} will not initialize properly."); +#endif + return; + } + int layers = m_Animator.layerCount; // Initializing the below arrays for everyone handles an issue // when running in owner authoritative mode and the owner changes. @@ -615,6 +622,9 @@ namespace Unity.Netcode.Components } } + // The total initialization size calculated for the m_ParameterWriter write buffer. + var totalParameterSize = sizeof(uint); + // Build our reference parameter values to detect when they change var parameters = m_Animator.parameters; m_CachedAnimatorParameters = new NativeArray(parameters.Length, Allocator.Persistent); @@ -655,7 +665,37 @@ namespace Unity.Netcode.Components } m_CachedAnimatorParameters[i] = cacheParam; + + // Calculate parameter sizes (index + type size) + switch (parameter.type) + { + case AnimatorControllerParameterType.Int: + { + totalParameterSize += sizeof(int) * 2; + break; + } + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + { + // Bool is serialized to 1 byte + totalParameterSize += sizeof(int) + 1; + break; + } + case AnimatorControllerParameterType.Float: + { + totalParameterSize += sizeof(int) + sizeof(float); + break; + } + } } + + if (m_ParameterWriter.IsInitialized) + { + m_ParameterWriter.Dispose(); + } + + // Create our parameter write buffer for serialization + m_ParameterWriter = new FastBufferWriter(totalParameterSize, Allocator.Persistent); } /// @@ -697,7 +737,7 @@ namespace Unity.Netcode.Components } /// - /// Wries all parameter and state information needed to initially synchronize a client + /// Writes all parameter and state information needed to initially synchronize a client /// private void WriteSynchronizationData(ref BufferSerializer serializer) where T : IReaderWriter { @@ -772,8 +812,10 @@ namespace Unity.Netcode.Components } } - animationState.Transition = isInTransition; // The only time this could be set to true - animationState.StateHash = stateHash; // When a transition, this is the originating/starting state + // The only time this could be set to true + animationState.Transition = isInTransition; + // When a transition, this is the originating/starting state + animationState.StateHash = stateHash; animationState.NormalizedTime = normalizedTime; animationState.Layer = layer; animationState.Weight = m_LayerWeights[layer]; @@ -847,7 +889,8 @@ namespace Unity.Netcode.Components { m_TransitionHash[layer] = nt.fullPathHash; m_AnimationHash[layer] = 0; - animState.DestinationStateHash = nt.fullPathHash; // Next state is the destination state for cross fade + // Next state is the destination state for cross fade + animState.DestinationStateHash = nt.fullPathHash; animState.CrossFade = true; animState.Transition = true; animState.Duration = tt.duration; @@ -865,7 +908,8 @@ namespace Unity.Netcode.Components // first time in this transition for this layer m_TransitionHash[layer] = tt.fullPathHash; m_AnimationHash[layer] = 0; - animState.StateHash = tt.fullPathHash; // Transitioning from state + // Transitioning from state + animState.StateHash = tt.fullPathHash; animState.CrossFade = false; animState.Transition = true; animState.NormalizedTime = tt.normalizedTime; @@ -1081,7 +1125,7 @@ namespace Unity.Netcode.Components { writer.Seek(0); writer.Truncate(); - // Write how many parameter entries we are going to write + // Write out how many parameter entries to read BytePacker.WriteValuePacked(writer, (uint)m_ParametersToUpdate.Count); foreach (var parameterIndex in m_ParametersToUpdate) { @@ -1230,10 +1274,11 @@ namespace Unity.Netcode.Components NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) sub-table does not contain destination state ({animationState.DestinationStateHash})!"); } } - else if (NetworkManager.LogLevel == LogLevel.Developer) - { - NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) does not exist!"); - } + // For reference, it is valid to have no transition information + //else if (NetworkManager.LogLevel == LogLevel.Developer) + //{ + // NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) does not exist!"); + //} } else if (animationState.Transition && animationState.CrossFade) { @@ -1436,7 +1481,7 @@ namespace Unity.Netcode.Components /// /// Distributed Authority: Internally-called RPC client receiving function to update a trigger when the server wants to forward - /// a trigger for a client to play / reset + /// a trigger to a client /// /// the payload containing the trigger data to apply [Rpc(SendTo.NotAuthority)] @@ -1447,7 +1492,7 @@ namespace Unity.Netcode.Components /// /// Client Server: Internally-called RPC client receiving function to update a trigger when the server wants to forward - /// a trigger for a client to play / reset + /// a trigger to a client /// /// the payload containing the trigger data to apply /// unused @@ -1513,7 +1558,7 @@ namespace Unity.Netcode.Components } /// - /// Resets the trigger for the associated animation. See SetTrigger for more on how triggers are special + /// Resets the trigger for the associated animation. See SetTrigger for more on how triggers are special /// /// The string name of the trigger to reset public void ResetTrigger(string triggerName) @@ -1529,4 +1574,5 @@ namespace Unity.Netcode.Components } } } -#endif // COM_UNITY_MODULES_ANIMATION +// COM_UNITY_MODULES_ANIMATION +#endif diff --git a/Runtime/Components/NetworkRigidBodyBase.cs b/Runtime/Components/NetworkRigidBodyBase.cs deleted file mode 100644 index 97930a9..0000000 --- a/Runtime/Components/NetworkRigidBodyBase.cs +++ /dev/null @@ -1,603 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace Unity.Netcode.Components -{ - /// - /// NetworkRigidbodyBase is a integration that helps to synchronize physics motion, collision, and interpolation - /// when used with a . - /// - /// - /// For a customizable netcode Rigidbody, create your own component from this class and use - /// during instantiation (i.e. invoked from within the Awake method). You can re-initialize after having initialized but only when the is not spawned. - /// - public abstract class NetworkRigidbodyBase : NetworkBehaviour - { -#if UNITY_EDITOR - [HideInInspector] - [SerializeField] - internal bool NetworkRigidbodyBaseExpanded; -#endif - - /// - /// When enabled, the associated will use the Rigidbody to apply and synchronize changes in position, rotation, and - /// allows for the use of Rigidbody interpolation/extrapolation. - /// - /// - /// If is enabled, non-authoritative instances can only use Rigidbody interpolation. If a network prefab is set to - /// extrapolation and is enabled, then non-authoritative instances will automatically be adjusted to use Rigidbody - /// interpolation while the authoritative instance will still use extrapolation. - /// - [Tooltip("When enabled and a NetworkTransform component is attached, the NetworkTransform will use the rigid body for motion and detecting changes in state.")] - public bool UseRigidBodyForMotion; - - /// - /// When enabled (default), automatically set the Kinematic state of the Rigidbody based on ownership. - /// When disabled, Kinematic state needs to be set by external script(s). - /// - public bool AutoUpdateKinematicState = true; - - /// - /// Primarily applies to the property when disabled but you still want - /// the Rigidbody to be automatically set to Kinematic when despawned. - /// - public bool AutoSetKinematicOnDespawn = true; - - // Used to cache the authority state of this Rigidbody during the last frame - private bool m_IsAuthority; - - protected internal Rigidbody m_InternalRigidbody { get; private set; } - - internal NetworkTransform NetworkTransform; - private float m_TickFrequency; - private float m_TickRate; - - private enum InterpolationTypes - { - None, - Interpolate, - Extrapolate - } - private InterpolationTypes m_OriginalInterpolation; - - /// - /// Initializes the networked Rigidbody based on the - /// passed in as a parameter. - /// - /// - /// Cannot be initialized while the associated is spawned. - /// - /// (optional) The to be used - protected void Initialize(NetworkTransform networkTransform = null, Rigidbody rigidbody = null) - { - // Don't initialize if already spawned - if (IsSpawned) - { - Debug.LogError($"[{name}] Attempting to initialize while spawned is not allowed."); - return; - } - m_InternalRigidbody = rigidbody; - NetworkTransform = networkTransform; - - if (m_InternalRigidbody == null) - { - m_InternalRigidbody = GetComponent(); - } - - SetOriginalInterpolation(); - - if (NetworkTransform == null) - { - NetworkTransform = GetComponent(); - } - - if (NetworkTransform != null) - { - NetworkTransform.RegisterRigidbody(this); - } - else - { - throw new System.Exception($"[Missing {nameof(NetworkTransform)}] No {nameof(NetworkTransform)} is assigned or can be found during initialization!"); - } - - if (AutoUpdateKinematicState) - { - SetIsKinematic(true); - } - } - - internal Vector3 GetAdjustedPositionThreshold() - { - // Since the threshold is a measurement of unity world space units per tick, we will allow for the maximum threshold - // to be no greater than the threshold measured in unity world space units per second - var thresholdMax = NetworkTransform.PositionThreshold * m_TickRate; - // Get the velocity in unity world space units per tick - var perTickVelocity = GetLinearVelocity() * m_TickFrequency; - // Since a rigid body can have "micro-motion" when allowed to come to rest (based on friction etc), we will allow for - // no less than 1/10th the threshold value. - var minThreshold = NetworkTransform.PositionThreshold * 0.1f; - - // Finally, we adjust the threshold based on the body's current velocity - perTickVelocity.x = Mathf.Clamp(Mathf.Abs(perTickVelocity.x), minThreshold, thresholdMax); - perTickVelocity.y = Mathf.Clamp(Mathf.Abs(perTickVelocity.y), minThreshold, thresholdMax); - perTickVelocity.z = Mathf.Clamp(Mathf.Abs(perTickVelocity.z), minThreshold, thresholdMax); - - return perTickVelocity; - } - - internal Vector3 GetAdjustedRotationThreshold() - { - // Since the rotation threshold is a measurement pf degrees per tick, we get the maximum threshold - // by calculating the threshold in degrees per second. - var thresholdMax = NetworkTransform.RotAngleThreshold * m_TickRate; - // Angular velocity is expressed in radians per second where as the rotation being checked is in degrees. - // Convert the angular velocity to degrees per second and then convert that to degrees per tick. - var rotationPerTick = (GetAngularVelocity() * Mathf.Rad2Deg) * m_TickFrequency; - var minThreshold = NetworkTransform.RotAngleThreshold * m_TickFrequency; - - rotationPerTick.x = Mathf.Clamp(Mathf.Abs(rotationPerTick.x), minThreshold, thresholdMax); - rotationPerTick.y = Mathf.Clamp(Mathf.Abs(rotationPerTick.y), minThreshold, thresholdMax); - rotationPerTick.z = Mathf.Clamp(Mathf.Abs(rotationPerTick.z), minThreshold, thresholdMax); - - return rotationPerTick; - } - - /// - /// Sets the linear velocity of the Rigidbody. - /// - public void SetLinearVelocity(Vector3 linearVelocity) - { - m_InternalRigidbody.linearVelocity = linearVelocity; - } - - /// - /// Gets the linear velocity of the Rigidbody. - /// - /// as the linear velocity - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3 GetLinearVelocity() - { - return m_InternalRigidbody.linearVelocity; - } - - /// - /// Sets the angular velocity for the Rigidbody. - /// - /// the angular velocity to apply to the body - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetAngularVelocity(Vector3 angularVelocity) - { - m_InternalRigidbody.angularVelocity = angularVelocity; - } - - /// - /// Gets the angular velocity for the Rigidbody. - /// - /// angular velocity as a - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3 GetAngularVelocity() - { - return m_InternalRigidbody.angularVelocity; - } - - /// - /// Gets the position of the Rigidbody - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3 GetPosition() - { - return m_InternalRigidbody.position; - } - - /// - /// Gets the rotation of the Rigidbody - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Quaternion GetRotation() - { - return m_InternalRigidbody.rotation; - } - - /// - /// Moves the rigid body - /// - /// The position to move towards - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void MovePosition(Vector3 position) - { - m_InternalRigidbody.MovePosition(position); - } - - /// - /// Directly applies a position (like teleporting) - /// - /// position to apply to the Rigidbody - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetPosition(Vector3 position) - { - m_InternalRigidbody.position = position; - } - - /// - /// Applies the rotation and position of the 's - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ApplyCurrentTransform() - { - m_InternalRigidbody.position = transform.position; - m_InternalRigidbody.rotation = transform.rotation; - } - - // Used for Rigidbody only (see info on normalized below) - private Vector4 m_QuaternionCheck = Vector4.zero; - - /// - /// Rotatates the Rigidbody towards a specified rotation - /// - /// The rotation expressed as a - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void MoveRotation(Quaternion rotation) - { - // Evidently we need to check to make sure the quaternion is a perfect - // magnitude of 1.0f when applying the rotation to a rigid body. - m_QuaternionCheck.x = rotation.x; - m_QuaternionCheck.y = rotation.y; - m_QuaternionCheck.z = rotation.z; - m_QuaternionCheck.w = rotation.w; - // If the magnitude is greater than 1.0f (even by a very small fractional value), then normalize the quaternion - if (m_QuaternionCheck.magnitude != 1.0f) - { - rotation.Normalize(); - } - m_InternalRigidbody.MoveRotation(rotation); - } - - /// - /// Applies a rotation to the Rigidbody - /// - /// The rotation to apply expressed as a - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetRotation(Quaternion rotation) - { - m_InternalRigidbody.rotation = rotation; - } - - /// - /// Sets the original interpolation of the Rigidbody while taking the Rigidbody type into consideration - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetOriginalInterpolation() - { - switch (m_InternalRigidbody.interpolation) - { - case RigidbodyInterpolation.None: - { - m_OriginalInterpolation = InterpolationTypes.None; - break; - } - case RigidbodyInterpolation.Interpolate: - { - m_OriginalInterpolation = InterpolationTypes.Interpolate; - break; - } - case RigidbodyInterpolation.Extrapolate: - { - m_OriginalInterpolation = InterpolationTypes.Extrapolate; - break; - } - } - } - - /// - /// Wakes the Rigidbody if it is sleeping - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WakeIfSleeping() - { - if (m_InternalRigidbody.IsSleeping()) - { - m_InternalRigidbody.WakeUp(); - } - } - - /// - /// Puts the Rigidbody to sleep - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SleepRigidbody() - { - m_InternalRigidbody.Sleep(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool IsKinematic() - { - return m_InternalRigidbody.isKinematic; - } - - /// - /// Sets the kinematic state of the Rigidbody and handles updating the Rigidbody's - /// interpolation setting based on the Kinematic state. - /// - /// - /// When using the Rigidbody for motion, this automatically - /// adjusts from extrapolation to interpolation if: - /// - The Rigidbody was originally set to extrapolation - /// - The NetworkTransform is set to interpolate - /// When the two above conditions are true: - /// - When switching from non-kinematic to kinematic this will automatically - /// switch the Rigidbody from extrapolation to interpolate. - /// - When switching from kinematic to non-kinematic this will automatically - /// switch the Rigidbody from interpolation back to extrapolation. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetIsKinematic(bool isKinematic) - { - m_InternalRigidbody.isKinematic = isKinematic; - - // If we are not spawned, then exit early - if (!IsSpawned) - { - return; - } - - if (UseRigidBodyForMotion) - { - // Only if the NetworkTransform is set to interpolate do we need to check for extrapolation - if (NetworkTransform.Interpolate && m_OriginalInterpolation == InterpolationTypes.Extrapolate) - { - if (IsKinematic()) - { - // If not already set to interpolate then set the Rigidbody to interpolate - if (m_InternalRigidbody.interpolation == RigidbodyInterpolation.Extrapolate) - { - // Sleep until the next fixed update when switching from extrapolation to interpolation - SleepRigidbody(); - SetInterpolation(InterpolationTypes.Interpolate); - } - } - else - { - // Switch it back to the original interpolation if non-kinematic (doesn't require sleep). - SetInterpolation(m_OriginalInterpolation); - } - } - } - else - { - SetInterpolation(m_IsAuthority ? m_OriginalInterpolation : (NetworkTransform.Interpolate ? InterpolationTypes.None : m_OriginalInterpolation)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetInterpolation(InterpolationTypes interpolationType) - { - switch (interpolationType) - { - case InterpolationTypes.None: - { - m_InternalRigidbody.interpolation = RigidbodyInterpolation.None; - break; - } - case InterpolationTypes.Interpolate: - { - m_InternalRigidbody.interpolation = RigidbodyInterpolation.Interpolate; - break; - } - case InterpolationTypes.Extrapolate: - { - m_InternalRigidbody.interpolation = RigidbodyInterpolation.Extrapolate; - break; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ResetInterpolation() - { - SetInterpolation(m_OriginalInterpolation); - } - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - UpdateOwnershipAuthority(); - base.OnOwnershipChanged(previous, current); - } - - /// - /// Sets the authority based on whether it is server or owner authoritative - /// - /// - /// Distributed authority sessions will always be owner authoritative. - /// - internal void UpdateOwnershipAuthority() - { - if (NetworkManager.DistributedAuthorityMode) - { - // When in distributed authority mode, always use HasAuthority - m_IsAuthority = HasAuthority; - } - else - { - if (NetworkTransform.IsServerAuthoritative()) - { - m_IsAuthority = NetworkManager.IsServer; - } - else - { - m_IsAuthority = IsOwner; - } - } - - if (AutoUpdateKinematicState) - { - SetIsKinematic(!m_IsAuthority); - } - } - - /// - public override void OnNetworkSpawn() - { - m_TickFrequency = 1.0f / NetworkManager.NetworkConfig.TickRate; - m_TickRate = NetworkManager.NetworkConfig.TickRate; - UpdateOwnershipAuthority(); - } - - /// - public override void OnNetworkDespawn() - { - if (UseRigidBodyForMotion && HasAuthority) - { - DetachFromFixedJoint(); - NetworkRigidbodyConnections.Clear(); - } - - // If we are automatically handling the kinematic state... - if (AutoUpdateKinematicState || AutoSetKinematicOnDespawn) - { - // Turn off physics for the rigid body until spawned, otherwise - // non-owners can run fixed updates before the first full - // NetworkTransform update and physics will be applied (i.e. gravity, etc) - SetIsKinematic(true); - } - SetInterpolation(m_OriginalInterpolation); - } - - // TODO: Possibly provide a NetworkJoint that allows for more options than fixed. - // Rigidbodies do not have the concept of "local space", and as such using a fixed joint will hold the object - // in place relative to the parent so jitter/stutter does not occur. - // Alternately, users can affix the fixed joint to a child GameObject (without a rigid body) of the parent NetworkObject - // and then add a NetworkTransform to that in order to get the parented child NetworkObject to move around in "local space" - public FixedJoint FixedJoint { get; private set; } - - internal System.Collections.Generic.List NetworkRigidbodyConnections = new System.Collections.Generic.List(); - internal NetworkRigidbodyBase ParentBody; - - private bool m_OriginalGravitySetting; - private float m_OriginalGravityScale; - - /// - /// When using a custom , this virtual method is invoked when the - /// is created in the event any additional adjustments are needed. - /// - protected virtual void OnFixedJointCreated() - { - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ApplyFixedJoint(NetworkRigidbodyBase bodyToConnectTo, Vector3 position, float connectedMassScale = 0.0f, float massScale = 1.0f, bool useGravity = false, bool zeroVelocity = true) - { - transform.position = position; - m_InternalRigidbody.position = position; - if (zeroVelocity) - { - m_InternalRigidbody.linearVelocity = Vector3.zero; - m_InternalRigidbody.angularVelocity = Vector3.zero; - } - m_OriginalGravitySetting = m_InternalRigidbody.useGravity; - m_InternalRigidbody.useGravity = useGravity; - FixedJoint = gameObject.AddComponent(); - FixedJoint.connectedBody = bodyToConnectTo.m_InternalRigidbody; - FixedJoint.connectedMassScale = connectedMassScale; - FixedJoint.massScale = massScale; - OnFixedJointCreated(); - } - - - /// - /// Authority Only: - /// When invoked and not already attached to a fixed joint, this will connect two rigid bodies with enabled. - /// Invoke this method on the rigid body you wish to attach to another (i.e. weapon to player, sticky bomb to player/object, etc). - /// - /// - /// - /// Parenting relative: - /// - This instance can be viewed as the child. - /// - The can be viewed as the parent. - ///
- /// This is the recommended way, as opposed to parenting, to attached/detatch two rigid bodies to one another when is enabled. - /// For more details on using . - ///
- /// This provides a simple joint solution between two rigid bodies and serves as an example. You can add different joint types by creating a customized/derived - /// version of . - ///
- /// The target object to attach to. - /// The position of the connection (i.e. where you want the object to be affixed). - /// The target object's mass scale relative to this object being attached. - /// This object's mass scale relative to the target object's. - /// Determines if this object will have gravity applied to it along with the object you are connecting this one to (the default is to not use gravity for this object) - /// When true (the default), both linear and angular velocities of this object are set to zero. - /// When true (the default), this object will teleport itself to the position of connection. - /// true (success) false (failed) - public bool AttachToFixedJoint(NetworkRigidbodyBase objectToConnectTo, Vector3 positionOfConnection, float connectedMassScale = 0.0f, float massScale = 1.0f, bool useGravity = false, bool zeroVelocity = true, bool teleportObject = true) - { - if (!UseRigidBodyForMotion) - { - Debug.LogError($"[{GetType().Name}] {name} does not have {nameof(UseRigidBodyForMotion)} set! Either enable {nameof(UseRigidBodyForMotion)} on this component or do not use a {nameof(FixedJoint)} when parenting under a {nameof(NetworkObject)}."); - return false; - } - - if (IsKinematic()) - { - Debug.LogError($"[{GetType().Name}] {name} is currently kinematic! You cannot use a {nameof(FixedJoint)} with Kinematic bodies!"); - return false; - } - - if (objectToConnectTo != null) - { - ApplyFixedJoint(objectToConnectTo, positionOfConnection, connectedMassScale, massScale, useGravity, zeroVelocity); - - ParentBody = objectToConnectTo; - ParentBody.NetworkRigidbodyConnections.Add(this); - if (teleportObject) - { - NetworkTransform.SetState(teleportDisabled: false); - } - return true; - } - return false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void RemoveFromParentBody() - { - ParentBody.NetworkRigidbodyConnections.Remove(this); - ParentBody = null; - } - - /// - /// Authority Only: - /// When invoked and already connected to an object via , - /// this will detach from the fixed joint and destroy the fixed joint component. - /// - /// - /// This is the recommended way, as opposed to parenting, to attached/detatch two rigid bodies to one another when is enabled. - /// - public void DetachFromFixedJoint() - { - if (!HasAuthority) - { - Debug.LogError($"[{name}] Only authority can invoke {nameof(DetachFromFixedJoint)}!"); - } - if (UseRigidBodyForMotion) - { - if (FixedJoint != null) - { - FixedJoint.connectedBody = null; - m_InternalRigidbody.useGravity = m_OriginalGravitySetting; - Destroy(FixedJoint); - FixedJoint = null; - ResetInterpolation(); - RemoveFromParentBody(); - } - } - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS - diff --git a/Runtime/Components/NetworkRigidBodyBase.cs.meta b/Runtime/Components/NetworkRigidBodyBase.cs.meta deleted file mode 100644 index 544ddba..0000000 --- a/Runtime/Components/NetworkRigidBodyBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8c4434f0563fb7f42b3b2993c97ae81a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Components/NetworkRigidbody.cs b/Runtime/Components/NetworkRigidbody.cs deleted file mode 100644 index 7d3d21e..0000000 --- a/Runtime/Components/NetworkRigidbody.cs +++ /dev/null @@ -1,24 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS -using UnityEngine; - -namespace Unity.Netcode.Components -{ - /// - /// NetworkRigidbody allows for the use of on network objects. By controlling the kinematic - /// mode of the and disabling it on all peers but the authoritative one. - /// - [RequireComponent(typeof(NetworkTransform))] - [RequireComponent(typeof(Rigidbody))] - [AddComponentMenu("Netcode/Network Rigidbody")] - public class NetworkRigidbody : NetworkRigidbodyBase - { - - public Rigidbody Rigidbody => m_InternalRigidbody; - - protected virtual void Awake() - { - Initialize(); - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS diff --git a/Runtime/Components/NetworkRigidbody.cs.meta b/Runtime/Components/NetworkRigidbody.cs.meta deleted file mode 100644 index 6f22401..0000000 --- a/Runtime/Components/NetworkRigidbody.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f6c0be61502bb534f922ebb746851216 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Components/NetworkRigidbody2D.cs b/Runtime/Components/NetworkRigidbody2D.cs deleted file mode 100644 index f7c9e14..0000000 --- a/Runtime/Components/NetworkRigidbody2D.cs +++ /dev/null @@ -1,22 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS2D -using UnityEngine; - -namespace Unity.Netcode.Components -{ - /// - /// NetworkRigidbody allows for the use of on network objects. By controlling the kinematic - /// mode of the rigidbody and disabling it on all peers but the authoritative one. - /// - [RequireComponent(typeof(NetworkTransform))] - [RequireComponent(typeof(Rigidbody2D))] - [AddComponentMenu("Netcode/Network Rigidbody 2D")] - public class NetworkRigidbody2D : NetworkRigidbodyBase - { - public Rigidbody2D Rigidbody2D => m_InternalRigidbody2D; - protected virtual void Awake() - { - Initialize(RigidbodyTypes.Rigidbody2D); - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS2D diff --git a/Runtime/Components/NetworkRigidbody2D.cs.meta b/Runtime/Components/NetworkRigidbody2D.cs.meta deleted file mode 100644 index f285546..0000000 --- a/Runtime/Components/NetworkRigidbody2D.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 80d7c879794dfda4687da0e400131852 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Components/NetworkTransform.cs b/Runtime/Components/NetworkTransform.cs index a103b0f..3d2be47 100644 --- a/Runtime/Components/NetworkTransform.cs +++ b/Runtime/Components/NetworkTransform.cs @@ -32,7 +32,8 @@ namespace Unity.Netcode.Components ///
public struct NetworkTransformState : INetworkSerializable { - private const int k_InLocalSpaceBit = 0x00000001; // Persists between state updates (authority dictates if this is set) + // Persists between state updates (authority dictates if this is set) + private const int k_InLocalSpaceBit = 0x00000001; private const int k_PositionXBit = 0x00000002; private const int k_PositionYBit = 0x00000004; private const int k_PositionZBit = 0x00000008; @@ -43,18 +44,25 @@ namespace Unity.Netcode.Components private const int k_ScaleYBit = 0x00000100; private const int k_ScaleZBit = 0x00000200; private const int k_TeleportingBit = 0x00000400; - private const int k_Interpolate = 0x00000800; // Persists between state updates (authority dictates if this is set) - private const int k_QuaternionSync = 0x00001000; // Persists between state updates (authority dictates if this is set) - private const int k_QuaternionCompress = 0x00002000; // Persists between state updates (authority dictates if this is set) - private const int k_UseHalfFloats = 0x00004000; // Persists between state updates (authority dictates if this is set) + // Persists between state updates (authority dictates if this is set) + private const int k_Interpolate = 0x00000800; + // Persists between state updates (authority dictates if this is set) + private const int k_QuaternionSync = 0x00001000; + // Persists between state updates (authority dictates if this is set) + private const int k_QuaternionCompress = 0x00002000; + // Persists between state updates (authority dictates if this is set) + private const int k_UseHalfFloats = 0x00004000; private const int k_Synchronization = 0x00008000; - private const int k_PositionSlerp = 0x00010000; // Persists between state updates (authority dictates if this is set) - private const int k_IsParented = 0x00020000; // When parented and synchronizing, we need to have both lossy and local scale due to varying spawn order + // Persists between state updates (authority dictates if this is set) + private const int k_PositionSlerp = 0x00010000; + // When parented and synchronizing, we need to have both lossy and local scale due to varying spawn order + private const int k_IsParented = 0x00020000; private const int k_SynchBaseHalfFloat = 0x00040000; private const int k_ReliableSequenced = 0x00080000; private const int k_UseUnreliableDeltas = 0x00100000; private const int k_UnreliableFrameSync = 0x00200000; - private const int k_TrackStateId = 0x10000000; // (Internal Debugging) When set each state update will contain a state identifier + // (Internal Debugging) When set each state update will contain a state identifier + private const int k_TrackStateId = 0x10000000; // Stores persistent and state relative flags private uint m_Bitset; @@ -409,8 +417,8 @@ namespace Unity.Netcode.Components } /// - /// Returns whether this state update was a frame synchronization when - /// UseUnreliableDeltas is enabled. When set, the entire transform will + /// Returns whether this state update was a frame synchronization when + /// UseUnreliableDeltas is enabled. When set, the entire transform will /// be or has been synchronized. /// public bool IsUnreliableFrameSync() @@ -929,8 +937,6 @@ namespace Unity.Netcode.Components #endregion #region PROPERTIES AND GENERAL METHODS - - public enum AuthorityModes { Server, @@ -1370,7 +1376,8 @@ namespace Unity.Netcode.Components private BufferedLinearInterpolatorVector3 m_PositionInterpolator; private BufferedLinearInterpolatorVector3 m_ScaleInterpolator; - private BufferedLinearInterpolatorQuaternion m_RotationInterpolator; // rotation is a single Quaternion since each Euler axis will affect the quaternion's final value + // rotation is a single Quaternion since each Euler axis will affect the quaternion's final value + private BufferedLinearInterpolatorQuaternion m_RotationInterpolator; // The previous network state private NetworkTransformState m_OldState = new NetworkTransformState(); @@ -1643,11 +1650,11 @@ namespace Unity.Netcode.Components Debug.LogException(ex); } - // The below is part of assuring we only send a frame synch, when sending unreliable deltas, if + // The below is part of assuring we only send a frame synch, when sending unreliable deltas, if // we have already sent at least one unreliable delta state update. At this point in the callstack, // a delta state update has just been sent in the above UpdateTransformState() call and as long as // we didn't send a frame synch and we are not synchronizing then we know at least one unreliable - // delta has been sent. Under this scenario, we should start checking for this instance's alloted + // delta has been sent. Under this scenario, we should start checking for this instance's alloted // frame synch "tick slot". Once we send a frame synch, if no other deltas occur after that // (i.e. the object is at rest) then we will stop sending frame synch's until the object begins // moving, rotating, or scaling again. @@ -1964,7 +1971,7 @@ namespace Unity.Netcode.Components networkState.NetworkDeltaPosition = m_HalfPositionState; - // If ownership offset is greater or we are doing an axial synchronization then synchronize the base position + // If ownership offset is greater or we are doing an axial synchronization then synchronize the base position if ((m_HalfFloatTargetTickOwnership > m_CachedNetworkManager.ServerTime.Tick || isAxisSync) && !networkState.IsTeleportingNextFrame) { networkState.SynchronizeBaseHalfFloat = true; @@ -3403,7 +3410,7 @@ namespace Unity.Netcode.Components /// - Local space to local space ( parent to parent) /// Will all smoothly transition while interpolation is enabled. /// (Does not work if using a or for motion) - /// + /// /// When a parent changes, non-authoritative instances should:
/// - Apply the resultant position, rotation, and scale from the parenting action.
/// - Clear interpolators (even if not enabled on this frame)
@@ -3575,7 +3582,7 @@ namespace Unity.Netcode.Components var transformToCommit = transform; - // Explicit set states are cumulative during a fractional tick period of time (i.e. each SetState invocation will + // Explicit set states are cumulative during a fractional tick period of time (i.e. each SetState invocation will // update the axial deltas to whatever changes are applied). As such, we need to preserve the dirty and explicit // state flags. var stateWasDirty = m_LocalAuthoritativeNetworkState.IsDirty; @@ -3658,7 +3665,7 @@ namespace Unity.Netcode.Components var serverTime = m_CachedNetworkManager.ServerTime; var cachedServerTime = serverTime.Time; - //var offset = (float)serverTime.TickOffset; + // var offset = (float)serverTime.TickOffset; #if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D var cachedDeltaTime = m_UseRigidbodyForMotion ? m_CachedNetworkManager.RealTimeProvider.FixedDeltaTime : m_CachedNetworkManager.RealTimeProvider.DeltaTime; #else @@ -3669,7 +3676,7 @@ namespace Unity.Netcode.Components // is to make their cachedRenderTime run 2 ticks behind. // TODO: This could most likely just always be 2 - //var ticksAgo = ((!IsServerAuthoritative() && !IsServer) || m_CachedNetworkManager.DistributedAuthorityMode) && !m_CachedNetworkManager.DAHost ? 2 : 1; + // var ticksAgo = ((!IsServerAuthoritative() && !IsServer) || m_CachedNetworkManager.DistributedAuthorityMode) && !m_CachedNetworkManager.DAHost ? 2 : 1; var ticksAgo = 2; var cachedRenderTime = serverTime.TimeTicksAgo(ticksAgo).Time; @@ -3746,7 +3753,7 @@ namespace Unity.Netcode.Components /// /// Determines whether the is or based on the property. - /// You can override this method to control this logic. + /// You can override this method to control this logic. /// /// or protected virtual bool OnIsServerAuthoritative() @@ -3772,7 +3779,6 @@ namespace Unity.Netcode.Components return OnIsServerAuthoritative(); } } - #endregion #region MESSAGE HANDLING @@ -3964,7 +3970,7 @@ namespace Unity.Netcode.Components { return 2 * m_TickFrequency; // TODO: We need an RTT that updates regularly and not just when the client sends packets - //return Mathf.Max(1.0f, TicksAgo) * m_TickFrequency; + // return Mathf.Max(1.0f, TicksAgo) * m_TickFrequency; } /// @@ -3974,25 +3980,25 @@ namespace Unity.Netcode.Components private void TickUpdate() { // TODO: We need an RTT that updates regularly and not just when the client sends packets - //if (m_UnityTransport != null) - //{ - // // Determine the desired ticks ago by the RTT (this really should be the combination of the - // // authority and non-authority 1/2 RTT but in the end anything beyond 300ms is considered very poor - // // network quality so latent interpolation is going to be expected). - // var rtt = Mathf.Max(m_TickInMS, m_UnityTransport.GetCurrentRtt(NetworkManager.ServerClientId)); - // m_TicksAgoSamples[m_TickSampleIndex] = Mathf.Max(1, (int)(rtt * m_TickFrequency)); - // var tickAgoSum = 0.0f; - // foreach (var tickAgo in m_TicksAgoSamples) - // { - // tickAgoSum += tickAgo; - // } - // m_PreviousTicksAgo = TicksAgo; - // TicksAgo = Mathf.Lerp(m_PreviousTicksAgo, tickAgoSum / m_TickRate, m_TickFrequency); - // m_TickSampleIndex = (m_TickSampleIndex + 1) % m_TickRate; - // // Get the partial tick value for when this is all calculated to provide an offset for determining - // // the relative starting interpolation point for the next update - // Offset = m_OffsetTickFrequency * (Mathf.Max(2, TicksAgo) - (int)TicksAgo); - //} + // if (m_UnityTransport != null) + // { + // // Determine the desired ticks ago by the RTT (this really should be the combination of the + // // authority and non-authority 1/2 RTT but in the end anything beyond 300ms is considered very poor + // // network quality so latent interpolation is going to be expected). + // var rtt = Mathf.Max(m_TickInMS, m_UnityTransport.GetCurrentRtt(NetworkManager.ServerClientId)); + // m_TicksAgoSamples[m_TickSampleIndex] = Mathf.Max(1, (int)(rtt * m_TickFrequency)); + // var tickAgoSum = 0.0f; + // foreach (var tickAgo in m_TicksAgoSamples) + // { + // tickAgoSum += tickAgo; + // } + // m_PreviousTicksAgo = TicksAgo; + // TicksAgo = Mathf.Lerp(m_PreviousTicksAgo, tickAgoSum / m_TickRate, m_TickFrequency); + // m_TickSampleIndex = (m_TickSampleIndex + 1) % m_TickRate; + // // Get the partial tick value for when this is all calculated to provide an offset for determining + // // the relative starting interpolation point for the next update + // Offset = m_OffsetTickFrequency * (Mathf.Max(2, TicksAgo) - (int)TicksAgo); + // } // TODO FIX: The local NetworkTickSystem can invoke with the same network tick as before if (m_NetworkManager.ServerTime.Tick <= m_LastTick) @@ -4012,13 +4018,13 @@ namespace Unity.Netcode.Components private UnityTransport m_UnityTransport; private float m_TickFrequency; - //private float m_OffsetTickFrequency; - //private ulong m_TickInMS; - //private int m_TickSampleIndex; + // private float m_OffsetTickFrequency; + // private ulong m_TickInMS; + // private int m_TickSampleIndex; private int m_TickRate; public float TicksAgo { get; private set; } - //public float Offset { get; private set; } - //private float m_PreviousTicksAgo; + // public float Offset { get; private set; } + // private float m_PreviousTicksAgo; private List m_TicksAgoSamples = new List(); @@ -4032,16 +4038,16 @@ namespace Unity.Netcode.Components //// For the offset, it uses the fractional remainder of the tick to determine the offset. //// In order to keep within tick boundaries, we increment the tick rate by 1 to assure it //// will always be < the tick frequency. - //m_OffsetTickFrequency = 1.0f / (m_TickRate + 1); - //m_TickInMS = (ulong)(1000 * m_TickFrequency); - //m_UnityTransport = m_NetworkManager.NetworkConfig.NetworkTransport as UnityTransport; + // m_OffsetTickFrequency = 1.0f / (m_TickRate + 1); + // m_TickInMS = (ulong)(1000 * m_TickFrequency); + // m_UnityTransport = m_NetworkManager.NetworkConfig.NetworkTransport as UnityTransport; //// Fill the sample with a starting value of 1 - //for (int i = 0; i < m_TickRate; i++) - //{ - // m_TicksAgoSamples.Add(1f); - //} + // for (int i = 0; i < m_TickRate; i++) + // { + // m_TicksAgoSamples.Add(1f); + // } TicksAgo = 2f; - //m_PreviousTicksAgo = 1f; + // m_PreviousTicksAgo = 1f; if (networkManager.IsServer) { networkManager.OnServerStopped += OnNetworkManagerStopped; diff --git a/Runtime/Components/RigidbodyContactEventManager.cs b/Runtime/Components/RigidbodyContactEventManager.cs index d0808d2..02f9c98 100644 --- a/Runtime/Components/RigidbodyContactEventManager.cs +++ b/Runtime/Components/RigidbodyContactEventManager.cs @@ -27,7 +27,7 @@ namespace Unity.Netcode.Components } /// - /// Default implementation required to register a with a instance. + /// Default implementation required to register a with a instance. /// /// /// Recommended to implement this method on a component @@ -52,7 +52,7 @@ namespace Unity.Netcode.Components } /// - /// This is an extended version of and can be used to register a with a instance.
+ /// This is an extended version of and can be used to register a with a instance.
/// This provides additional information to the for each set of contact events it is processing. ///
public interface IContactEventHandlerWithInfo : IContactEventHandler @@ -66,9 +66,9 @@ namespace Unity.Netcode.Components /// /// Add this component to an in-scene placed GameObject to provide faster collision event processing between instances and optionally static colliders. - ///
- ///
- ///
+ ///
+ ///
+ ///
///
[AddComponentMenu("Netcode/Rigidbody Contact Event Manager")] public class RigidbodyContactEventManager : MonoBehaviour diff --git a/Runtime/Configuration/NetworkConfig.cs b/Runtime/Configuration/NetworkConfig.cs index 79035a8..a966808 100644 --- a/Runtime/Configuration/NetworkConfig.cs +++ b/Runtime/Configuration/NetworkConfig.cs @@ -13,6 +13,14 @@ namespace Unity.Netcode [Serializable] public class NetworkConfig { + // Clamp spawn time outs to prevent dropping messages during scene events + // Note: The legacy versions of NGO defaulted to 1s which was too low. As + // well, the SpawnTimeOut is now being clamped to within this recommended + // range both via UI and when NetworkManager is validated. + internal const float MinSpawnTimeout = 10.0f; + // Clamp spawn time outs to no more than 1 hour (really that is a bit high) + internal const float MaxSpawnTimeout = 3600.0f; + /// /// The protocol version. Different versions doesn't talk to each other. /// @@ -132,6 +140,8 @@ namespace Unity.Netcode /// The amount of time a message will be held (deferred) if the destination NetworkObject needed to process the message doesn't exist yet. If the NetworkObject is not spawned within this time period, all deferred messages for that NetworkObject will be dropped. ///
[Tooltip("The amount of time a message will be held (deferred) if the destination NetworkObject needed to process the message doesn't exist yet. If the NetworkObject is not spawned within this time period, all deferred messages for that NetworkObject will be dropped.")] + + [Range(MinSpawnTimeout, MaxSpawnTimeout)] public float SpawnTimeout = 10f; /// @@ -176,6 +186,21 @@ namespace Unity.Netcode [Tooltip("Enable (default) if you want to profile network messages with development builds and defaults to being disabled in release builds. When disabled, network messaging profiling will be disabled in development builds.")] public bool NetworkProfilingMetrics = true; + /// + /// Invoked by when it is validated. + /// + /// + /// Used to check for potential legacy values that have already been serialized and/or + /// runtime modifications to a property outside of the recommended range. + /// For each property checked below, provide a brief description of the reason. + /// + internal void OnValidate() + { + // Legacy NGO versions defaulted this value to 1 second that has since been determiend + // any range less than 10 seconds can lead to dropped messages during scene events. + SpawnTimeout = Mathf.Clamp(SpawnTimeout, MinSpawnTimeout, MaxSpawnTimeout); + } + /// /// Returns a base64 encoded version of the configuration /// diff --git a/Runtime/Configuration/SessionConfig.cs b/Runtime/Configuration/SessionConfig.cs new file mode 100644 index 0000000..671ae74 --- /dev/null +++ b/Runtime/Configuration/SessionConfig.cs @@ -0,0 +1,58 @@ +namespace Unity.Netcode +{ + internal class SessionConfig + { + /// + /// The running list of session versions + /// + public const uint NoFeatureCompatibility = 0; + public const uint BypassFeatureCompatible = 1; + public const uint ServerDistributionCompatible = 2; + + // The most current session version (!!!!set this when you increment!!!!!) + public static uint PackageSessionVersion => ServerDistributionCompatible; + + internal uint SessionVersion; + + public bool ServiceSideDistribution; + + + /// + /// Service to client + /// Set when the client receives a + /// + /// the session's settings + public SessionConfig(ServiceConfig serviceConfig) + { + SessionVersion = serviceConfig.SessionVersion; + ServiceSideDistribution = serviceConfig.ServerRedistribution; + } + + /// + /// Can be used to directly set the version. + /// + /// + /// If a client connects that does not support session configuration then + /// this will be invoked. The default values set in the constructor should + /// assume that no features are available. + /// Can also be used for mock/integration testing version handling. + /// + /// version to set + public SessionConfig(uint version) + { + SessionVersion = version; + ServiceSideDistribution = false; + } + + /// + /// Client to Service + /// Default package constructor set when is invoked. + /// + public SessionConfig() + { + // The current + SessionVersion = PackageSessionVersion; + ServiceSideDistribution = false; + } + } +} diff --git a/Runtime/Configuration/SessionConfig.cs.meta b/Runtime/Configuration/SessionConfig.cs.meta new file mode 100644 index 0000000..bb361b9 --- /dev/null +++ b/Runtime/Configuration/SessionConfig.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e0512e5a3e1dc484bbbf98c03a574645 \ No newline at end of file diff --git a/Runtime/Connection/NetworkConnectionManager.cs b/Runtime/Connection/NetworkConnectionManager.cs index 9f59401..fe6bc48 100644 --- a/Runtime/Connection/NetworkConnectionManager.cs +++ b/Runtime/Connection/NetworkConnectionManager.cs @@ -10,27 +10,54 @@ using UnityEngine; namespace Unity.Netcode { - + /// + /// The connection event type set within to signify the type of connection event notification received. + /// + /// + /// is returned as a parameter of the event notification. + /// and event types occur on the client-side of the newly connected client and on the server-side.
+ /// and event types occur on connected clients to notify that a new client (peer) has joined/connected. + ///
public enum ConnectionEvent { /// - /// Invoked on the server when a client connected. + /// This event is set on the client-side of the newly connected client and on the server-side.
///
+ /// + /// On the newly connected client side, the will be the .
+ /// On the server side, the will be the ID of the client that just connected. + ///
ClientConnected, /// - /// Invoked on all clients when a client connected. + /// This event is set on clients that are already connected to the session. /// + /// + /// The will be the ID of the client that just connected. + /// PeerConnected, /// - /// Invoked on all clients when a client disconnected. + /// This event is set on the client-side of the client that disconnected client and on the server-side. /// + /// + /// On the disconnected client side, the will be the .
+ /// On the server side, this will be the ID of the client that disconnected. + ///
ClientDisconnected, /// - /// Invoked on all clients when a client disconnected. + /// This event is set on clients that are already connected to the session. /// + /// + /// The will be the ID of the client that just disconnected. + /// PeerDisconnected } + /// + /// Returned as a parameter of the event notification. + /// + /// + /// See for more details on the types of connection events received. + /// public struct ConnectionEventData { public ConnectionEvent EventType; @@ -575,7 +602,7 @@ namespace Unity.Netcode { var message = new ConnectionRequestMessage { - CMBServiceConnection = NetworkManager.CMBServiceConnection, + DistributedAuthority = NetworkManager.DistributedAuthorityMode, // Since only a remote client will send a connection request, we should always force the rebuilding of the NetworkConfig hash value ConfigHash = NetworkManager.NetworkConfig.GetConfig(false), ShouldSendConnectionData = NetworkManager.NetworkConfig.ConnectionApproval, @@ -583,8 +610,9 @@ namespace Unity.Netcode MessageVersions = new NativeArray(MessageManager.MessageHandlers.Length, Allocator.Temp) }; - if (NetworkManager.CMBServiceConnection) + if (NetworkManager.DistributedAuthorityMode) { + message.ClientConfig.SessionConfig = NetworkManager.SessionConfig; message.ClientConfig.TickRate = NetworkManager.NetworkConfig.TickRate; message.ClientConfig.EnableSceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement; } @@ -1013,6 +1041,14 @@ namespace Unity.Netcode } var distributedAuthority = NetworkManager.DistributedAuthorityMode; + + // If not using DA return early or if using DA and scene management is disabled then exit early Since we use NetworkShow to spawn + // objects on the newly connected client side. + if (!distributedAuthority || distributedAuthority && !NetworkManager.NetworkConfig.EnableSceneManagement) + { + return networkClient; + } + var sessionOwnerId = NetworkManager.CurrentSessionOwner; var isSessionOwner = NetworkManager.LocalClient.IsSessionOwner; foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList) @@ -1176,7 +1212,7 @@ namespace Unity.Netcode { // Only NetworkObjects that have the OwnershipStatus.Distributable flag set and no parent // (ownership is transferred to all children) will have their ownership redistributed. - if (ownedObject.IsOwnershipDistributable && ownedObject.GetCachedParent() == null) + if (ownedObject.IsOwnershipDistributable && ownedObject.GetCachedParent() == null && !ownedObject.IsOwnershipSessionOwner) { if (ownedObject.IsOwnershipLocked) { @@ -1213,6 +1249,11 @@ namespace Unity.Netcode childObject.SetOwnershipLock(false); } + // Ignore session owner marked objects + if (childObject.IsOwnershipSessionOwner) + { + continue; + } NetworkManager.SpawnManager.ChangeOwnership(childObject, targetOwner, true); if (EnableDistributeLogging) { diff --git a/Runtime/Core/NetworkBehaviour.cs b/Runtime/Core/NetworkBehaviour.cs index bcdd25f..adc7ec0 100644 --- a/Runtime/Core/NetworkBehaviour.cs +++ b/Runtime/Core/NetworkBehaviour.cs @@ -826,7 +826,7 @@ namespace Unity.Netcode internal void InternalOnGainedOwnership() { UpdateNetworkProperties(); - // New owners need to assure any NetworkVariables they have write permissions + // New owners need to assure any NetworkVariables they have write permissions // to are updated so the previous and original values are aligned with the // current value (primarily for collections). if (OwnerClientId == NetworkManager.LocalClientId) @@ -1181,14 +1181,8 @@ namespace Unity.Netcode { // Create any values that require accessing the NetworkManager locally (it is expensive to access it in NetworkBehaviour) var networkManager = NetworkManager; - var distributedAuthority = networkManager.DistributedAuthorityMode; var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety; - // Always write the NetworkVariable count even if zero for distributed authority (used by comb server) - if (distributedAuthority) - { - writer.WriteValueSafe((ushort)NetworkVariableFields.Count); - } // Exit early if there are no NetworkVariables if (NetworkVariableFields.Count == 0) @@ -1203,14 +1197,8 @@ namespace Unity.Netcode if (NetworkVariableFields[j].CanClientRead(targetClientId)) { // Write additional NetworkVariable information when length safety is enabled or when in distributed authority mode - if (ensureLengthSafety || distributedAuthority) + if (ensureLengthSafety) { - // Write the type being serialized for distributed authority (only for comb-server) - if (distributedAuthority) - { - writer.WriteValueSafe(NetworkVariableFields[j].Type); - } - var writePos = writer.Position; // Note: This value can't be packed because we don't know how large it will be in advance // we reserve space for it, then write the data, then come back and fill in the space @@ -1261,20 +1249,8 @@ namespace Unity.Netcode { // Stack cache any values that requires accessing the NetworkManager (it is expensive to access it in NetworkBehaviour) var networkManager = NetworkManager; - var distributedAuthority = networkManager.DistributedAuthorityMode; var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety; - // Always read the NetworkVariable count when in distributed authority (sanity check if comb-server matches what client has locally) - if (distributedAuthority) - { - reader.ReadValueSafe(out ushort variableCount); - if (variableCount != NetworkVariableFields.Count) - { - Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}] NetworkVariable count mismatch! (Read: {variableCount} vs. Expected: {NetworkVariableFields.Count})"); - return; - } - } - // Exit early if nothing else to read if (NetworkVariableFields.Count == 0) { @@ -1289,14 +1265,8 @@ namespace Unity.Netcode // Distributed Authority: All clients have read permissions, always try to read the value if (NetworkVariableFields[j].CanClientRead(clientId)) { - if (ensureLengthSafety || distributedAuthority) + if (ensureLengthSafety) { - // Read the type being serialized and discard it (for now) when in a distributed authority network topology (only used by comb-server) - if (distributedAuthority) - { - reader.ReadValueSafe(out NetworkVariableType _); - } - reader.ReadValueSafe(out varSize); if (varSize == 0) { @@ -1320,11 +1290,11 @@ namespace Unity.Netcode continue; } - // Read the NetworkVarible value + // Read the NetworkVariable value NetworkVariableFields[j].ReadField(reader); - // When EnsureNetworkVariableLengthSafety or DistributedAuthorityMode always do a bounds check - if (ensureLengthSafety || distributedAuthority) + // When EnsureNetworkVariableLengthSafety always do a bounds check + if (ensureLengthSafety) { if (reader.Position > (readStartPos + varSize)) { diff --git a/Runtime/Core/NetworkBehaviourUpdater.cs b/Runtime/Core/NetworkBehaviourUpdater.cs index 9062ebf..6a1dd74 100644 --- a/Runtime/Core/NetworkBehaviourUpdater.cs +++ b/Runtime/Core/NetworkBehaviourUpdater.cs @@ -141,6 +141,9 @@ namespace Unity.Netcode // Then show any NetworkObjects queued to be made visible/shown m_NetworkManager.SpawnManager.HandleNetworkObjectShow(); + + // Handle object redistribution (DA + disabled scene management only) + m_NetworkManager.HandleRedistributionToClients(); } } } diff --git a/Runtime/Core/NetworkManager.cs b/Runtime/Core/NetworkManager.cs index de08ae0..9b3ef04 100644 --- a/Runtime/Core/NetworkManager.cs +++ b/Runtime/Core/NetworkManager.cs @@ -80,6 +80,18 @@ namespace Unity.Netcode } #endif + internal SessionConfig SessionConfig; + + /// + /// Used for internal testing purposes + /// + internal delegate SessionConfig OnGetSessionConfigHandler(); + internal OnGetSessionConfigHandler OnGetSessionConfig; + private SessionConfig GetSessionConfig() + { + return OnGetSessionConfig != null ? OnGetSessionConfig.Invoke() : new SessionConfig(); + } + internal static bool IsDistributedAuthority; /// @@ -162,10 +174,30 @@ namespace Unity.Netcode } } - // DANGO-TODO-MVP: Remove these properties once the service handles object distribution - internal ulong ClientToRedistribute; - internal bool RedistributeToClient; - internal int TickToRedistribute; + // DANGO-TODO: Determine if this needs to be removed once the service handles object distribution + internal List ClientsToRedistribute = new List(); + internal bool RedistributeToClients; + + /// + /// Handles object redistribution when scene management is disabled. + /// + /// DANGO-TODO: Determine if this needs to be removed once the service handles object distribution + /// + internal void HandleRedistributionToClients() + { + if (!DistributedAuthorityMode || !RedistributeToClients || NetworkConfig.EnableSceneManagement || ShutdownInProgress) + { + return; + } + + foreach (var clientId in ClientsToRedistribute) + { + SpawnManager.DistributeNetworkObjects(clientId); + } + RedistributeToClients = false; + ClientsToRedistribute.Clear(); + } + internal List DeferredDespawnObjects = new List(); @@ -193,11 +225,7 @@ namespace Unity.Netcode foreach (var networkObjectEntry in SpawnManager.SpawnedObjects) { var networkObject = networkObjectEntry.Value; - if (networkObject.IsSceneObject == null || !networkObject.IsSceneObject.Value) - { - continue; - } - if (networkObject.OwnerClientId != LocalClientId) + if (networkObject.IsOwnershipSessionOwner && LocalClient.IsSessionOwner) { SpawnManager.ChangeOwnership(networkObject, LocalClientId, true); } @@ -291,6 +319,10 @@ namespace Unity.Netcode case NetworkUpdateStage.EarlyUpdate: { UpdateTopology(); + + // Handle processing any new connections or transport events + NetworkConfig.NetworkTransport.EarlyUpdate(); + ConnectionManager.ProcessPendingApprovals(); ConnectionManager.PollAndHandleNetworkEvents(); @@ -298,6 +330,7 @@ namespace Unity.Netcode AnticipationSystem.SetupForUpdate(); MessageManager.ProcessIncomingMessageQueue(); + MessageManager.CleanupDisconnectedClients(); AnticipationSystem.ProcessReanticipation(); } @@ -379,22 +412,15 @@ namespace Unity.Netcode // Metrics update needs to be driven by NetworkConnectionManager's update to assure metrics are dispatched after the send queue is processed. MetricsManager.UpdateMetrics(); + // Handle sending any pending transport messages + NetworkConfig.NetworkTransport.PostLateUpdate(); + // TODO: Determine a better way to handle this NetworkObject.VerifyParentingStatus(); // This is "ok" to invoke when not processing messages since it is just cleaning up messages that never got handled within their timeout period. DeferredMessageManager.CleanupStaleTriggers(); - // DANGO-TODO-MVP: Remove this once the service handles object distribution - // NOTE: This needs to be the last thing done and should happen exactly at this point - // in the update - if (RedistributeToClient && ServerTime.Tick <= TickToRedistribute) - { - RedistributeToClient = false; - SpawnManager.DistributeNetworkObjects(ClientToRedistribute); - ClientToRedistribute = 0; - } - if (m_ShuttingDown) { // Host-server will disconnect any connected clients prior to finalizing its shutdown @@ -925,6 +951,9 @@ namespace Unity.Netcode return; // May occur when the component is added } + // Do a validation pass on NetworkConfig properties + NetworkConfig.OnValidate(); + if (GetComponentInChildren() != null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) @@ -993,8 +1022,7 @@ namespace Unity.Netcode { if (IsListening && change == PlayModeStateChange.ExitingPlayMode) { - // Make sure we are not holding onto anything in case domain reload is disabled - ShutdownInternal(); + OnApplicationQuit(); } } #endif @@ -1161,6 +1189,12 @@ namespace Unity.Netcode UpdateTopology(); + // Always create a default session config when starting a NetworkManager instance + if (DistributedAuthorityMode) + { + SessionConfig = GetSessionConfig(); + } + // Make sure the ServerShutdownState is reset when initializing if (server) { diff --git a/Runtime/Core/NetworkObject.cs b/Runtime/Core/NetworkObject.cs index 3ccd8ea..c449c9a 100644 --- a/Runtime/Core/NetworkObject.cs +++ b/Runtime/Core/NetworkObject.cs @@ -102,10 +102,22 @@ namespace Unity.Netcode private const int k_SceneObjectType = 2; private const int k_SourceAssetObjectType = 3; + // Used to track any InContext or InIsolation prefab being edited. + private static PrefabStage s_PrefabStage; + // The network prefab asset that the edit mode scene has created an instance of (s_PrefabInstance). + private static NetworkObject s_PrefabAsset; + // The InContext or InIsolation edit mode network prefab scene instance of the prefab asset (s_PrefabAsset). + private static NetworkObject s_PrefabInstance; + + private static bool s_DebugPrefabIdGeneration; + + [ContextMenu("Refresh In-Scene Prefab Instances")] internal void RefreshAllPrefabInstances() { var instanceGlobalId = GlobalObjectId.GetGlobalObjectIdSlow(this); + // Assign the currently selected instance to be updated + NetworkObjectRefreshTool.PrefabNetworkObject = this; if (!PrefabUtility.IsPartOfAnyPrefab(this) || instanceGlobalId.identifierType != k_ImportedAssetObjectType) { EditorUtility.DisplayDialog("Network Prefab Assets Only", "This action can only be performed on a network prefab asset.", "Ok"); @@ -132,25 +144,119 @@ namespace Unity.Netcode NetworkObjectRefreshTool.ProcessScenes(); } + /// + /// Register for opened and closing event notifications. + /// + [InitializeOnLoadMethod] + private static void OnApplicationStart() + { + PrefabStage.prefabStageOpened -= PrefabStageOpened; + PrefabStage.prefabStageOpened += PrefabStageOpened; + PrefabStage.prefabStageClosing -= PrefabStageClosing; + PrefabStage.prefabStageClosing += PrefabStageClosing; + } + + private static void PrefabStageClosing(PrefabStage prefabStage) + { + // If domain reloading is enabled, then this will be null when we return from playmode. + if (s_PrefabStage == null) + { + // Determine if we have a network prefab opened in edit mode or not. + CheckPrefabStage(prefabStage); + } + + s_PrefabStage = null; + s_PrefabInstance = null; + s_PrefabAsset = null; + } + + private static void PrefabStageOpened(PrefabStage prefabStage) + { + // Determine if we have a network prefab opened in edit mode or not. + CheckPrefabStage(prefabStage); + } + + /// + /// Determines if we have opened a network prefab in edit mode (InContext or InIsolation) + /// + /// + /// InContext: Typically means a are in prefab edit mode for an in-scene placed network prefab instance. + /// (currently no such thing as a network prefab with nested network prefab instances) + /// + /// InIsolation: Typically means we are in prefb edit mode for a prefab asset. + /// + /// + private static void CheckPrefabStage(PrefabStage prefabStage) + { + s_PrefabStage = prefabStage; + s_PrefabInstance = prefabStage.prefabContentsRoot?.GetComponent(); + if (s_PrefabInstance) + { + // We acquire the source prefab that the prefab edit mode scene instance was instantiated from differently for InContext than InSolation. + if (s_PrefabStage.mode == PrefabStage.Mode.InContext && s_PrefabStage.openedFromInstanceRoot != null) + { + // This is needed to handle the scenario where a user completely loads a new scene while in an InContext prefab edit mode. + try + { + s_PrefabAsset = s_PrefabStage.openedFromInstanceRoot?.GetComponent(); + } + catch + { + s_PrefabAsset = null; + } + } + else + { + // When editing in InIsolation mode, load the original prefab asset from the provided path. + s_PrefabAsset = AssetDatabase.LoadAssetAtPath(s_PrefabStage.assetPath); + } + + if (s_PrefabInstance.GlobalObjectIdHash != s_PrefabAsset.GlobalObjectIdHash) + { + s_PrefabInstance.GlobalObjectIdHash = s_PrefabAsset.GlobalObjectIdHash; + // For InContext mode, we don't want to record these modifications (the in-scene GlobalObjectIdHash is serialized with the scene). + if (s_PrefabStage.mode == PrefabStage.Mode.InIsolation) + { + PrefabUtility.RecordPrefabInstancePropertyModifications(s_PrefabAsset); + } + } + } + else + { + s_PrefabStage = null; + s_PrefabInstance = null; + s_PrefabAsset = null; + } + } + + /// + /// GlobalObjectIdHash values are generated during validation. + /// internal void OnValidate() { - // do NOT regenerate GlobalObjectIdHash for NetworkPrefabs while Editor is in PlayMode + // Always exit early if we are in prefab edit mode and this instance is the + // prefab instance within the InContext or InIsolation edit scene. + if (s_PrefabInstance == this) + { + return; + } + + // Do not regenerate GlobalObjectIdHash for NetworkPrefabs while Editor is in play mode. if (EditorApplication.isPlaying && !string.IsNullOrEmpty(gameObject.scene.name)) { return; } - // do NOT regenerate GlobalObjectIdHash if Editor is transitioning into or out of PlayMode + // Do not regenerate GlobalObjectIdHash if Editor is transitioning into or out of play mode. if (!EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode) { return; } - // Get a global object identifier for this network prefab - var globalId = GetGlobalId(); + // Get a global object identifier for this network prefab. + var globalId = GlobalObjectId.GetGlobalObjectIdSlow(this); - - // if the identifier type is 0, then don't update the GlobalObjectIdHash + // if the identifier type is 0, then don't update the GlobalObjectIdHash. if (globalId.identifierType == k_NullObjectType) { return; @@ -159,47 +265,34 @@ namespace Unity.Netcode var oldValue = GlobalObjectIdHash; GlobalObjectIdHash = globalId.ToString().Hash32(); - // If the GlobalObjectIdHash value changed, then mark the asset dirty + // Always check for in-scene placed to assure any previous version scene assets with in-scene place NetworkObjects gets updated. + CheckForInScenePlaced(); + + // If the GlobalObjectIdHash value changed, then mark the asset dirty. if (GlobalObjectIdHash != oldValue) { - // Check if this is an in-scnee placed NetworkObject (Special Case for In-Scene Placed) - if (!IsEditingPrefab() && gameObject.scene.name != null && gameObject.scene.name != gameObject.name) + // Check if this is an in-scnee placed NetworkObject (Special Case for In-Scene Placed). + if (IsSceneObject.HasValue && IsSceneObject.Value) { - // Sanity check to make sure this is a scene placed object + // Sanity check to make sure this is a scene placed object. if (globalId.identifierType != k_SceneObjectType) { - // This should never happen, but in the event it does throw and error + // This should never happen, but in the event it does throw and error. Debug.LogError($"[{gameObject.name}] is detected as an in-scene placed object but its identifier is of type {globalId.identifierType}! **Report this error**"); } - // If this is a prefab instance + // If this is a prefab instance, then we want to mark it as having been updated in order for the udpated GlobalObjectIdHash value to be saved. if (PrefabUtility.IsPartOfAnyPrefab(this)) { - // We must invoke this in order for the modifications to get saved with the scene (does not mark scene as dirty) + // We must invoke this in order for the modifications to get saved with the scene (does not mark scene as dirty). PrefabUtility.RecordPrefabInstancePropertyModifications(this); } } - else // Otherwise, this is a standard network prefab asset so we just mark it dirty for the AssetDatabase to update it + else // Otherwise, this is a standard network prefab asset so we just mark it dirty for the AssetDatabase to update it. { EditorUtility.SetDirty(this); } } - - // Always check for in-scene placed to assure any previous version scene assets with in-scene place NetworkObjects gets updated - CheckForInScenePlaced(); - } - - private bool IsEditingPrefab() - { - // Check if we are directly editing the prefab - var stage = PrefabStageUtility.GetPrefabStage(gameObject); - - // if we are not editing the prefab directly (or a sub-prefab), then return the object identifier - if (stage == null || stage.assetPath == null) - { - return false; - } - return true; } /// @@ -210,13 +303,12 @@ namespace Unity.Netcode /// /// This NetworkObject is considered an in-scene placed prefab asset instance if it is: /// - Part of a prefab - /// - Not being directly edited /// - Within a valid scene that is part of the scenes in build list /// (In-scene defined NetworkObjects that are not part of a prefab instance are excluded.) /// private void CheckForInScenePlaced() { - if (PrefabUtility.IsPartOfAnyPrefab(this) && !IsEditingPrefab() && gameObject.scene.IsValid() && gameObject.scene.isLoaded && gameObject.scene.buildIndex >= 0) + if (PrefabUtility.IsPartOfAnyPrefab(this) && gameObject.scene.IsValid() && gameObject.scene.isLoaded && gameObject.scene.buildIndex >= 0) { var prefab = PrefabUtility.GetCorrespondingObjectFromSource(gameObject); var assetPath = AssetDatabase.GetAssetPath(prefab); @@ -229,55 +321,6 @@ namespace Unity.Netcode IsSceneObject = true; } } - - private GlobalObjectId GetGlobalId() - { - var instanceGlobalId = GlobalObjectId.GetGlobalObjectIdSlow(this); - - // If not editing a prefab, then just use the generated id - if (!IsEditingPrefab()) - { - return instanceGlobalId; - } - - // If the asset doesn't exist at the given path, then return the object identifier - var prefabStageAssetPath = PrefabStageUtility.GetPrefabStage(gameObject).assetPath; - // If (for some reason) the asset path is null return the generated id - if (prefabStageAssetPath == null) - { - return instanceGlobalId; - } - - var theAsset = AssetDatabase.LoadAssetAtPath(prefabStageAssetPath); - // If there is no asset at that path (for some odd/edge case reason), return the generated id - if (theAsset == null) - { - return instanceGlobalId; - } - - // If we can't get the asset GUID and/or the file identifier, then return the object identifier - if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(theAsset, out var guid, out long localFileId)) - { - return instanceGlobalId; - } - - // Note: If we reached this point, then we are most likely opening a prefab to edit. - // The instanceGlobalId will be constructed as if it is a scene object, however when it - // is serialized its value will be treated as a file asset (the "why" to the below code). - - // Construct an imported asset identifier with the type being a source asset object type - var prefabGlobalIdText = string.Format(k_GlobalIdTemplate, k_SourceAssetObjectType, guid, (ulong)localFileId, 0); - - // If we can't parse the result log an error and return the instanceGlobalId - if (!GlobalObjectId.TryParse(prefabGlobalIdText, out var prefabGlobalId)) - { - Debug.LogError($"[GlobalObjectId Gen] Failed to parse ({prefabGlobalIdText}) returning default ({instanceGlobalId})! ** Please Report This Error **"); - return instanceGlobalId; - } - - // Otherwise, return the constructed identifier for the source prefab asset - return prefabGlobalId; - } #endif // UNITY_EDITOR /// @@ -396,6 +439,13 @@ namespace Unity.Netcode /// public bool IsOwnershipDistributable => Ownership.HasFlag(OwnershipStatus.Distributable); + /// + /// When true, the can only be owned by the current Session Owner. + /// To set during runtime, use to ensure the session owner owns the object. + /// Once the session owner owns the object, then use . + /// + public bool IsOwnershipSessionOwner => Ownership.HasFlag(OwnershipStatus.SessionOwner); + /// /// Returns true if the is has ownership locked. /// When locked, the cannot be redistributed nor can it be transferred by another client. @@ -438,7 +488,8 @@ namespace Unity.Netcode /// : If nothing is set, then ownership is considered "static" and cannot be redistributed, requested, or transferred (i.e. a Player would have this). /// : When set, this instance will be automatically redistributed when a client joins (if not locked or no request is pending) or leaves. /// : When set, a non-owner can obtain ownership immediately (without requesting and as long as it is not locked). - /// : When set, When set, a non-owner must request ownership from the owner (will always get locked once ownership is transferred). + /// : When set, a non-owner must request ownership from the owner (will always get locked once ownership is transferred). + /// : When set, only the current session owner may have ownership over this object. /// // Ranges from 1 to 8 bits [Flags] @@ -448,6 +499,7 @@ namespace Unity.Netcode Distributable = 1 << 0, Transferable = 1 << 1, RequestRequired = 1 << 2, + SessionOwner = 1 << 3, } /// @@ -506,7 +558,7 @@ namespace Unity.Netcode } // If we don't have the Transferable flag set and it is not a player object, then it is the same as having a static lock on ownership - if (!IsOwnershipTransferable && !IsPlayerObject) + if (!(IsOwnershipTransferable || IsPlayerObject) || IsOwnershipSessionOwner) { NetworkLog.LogWarning($"Trying to add or remove ownership lock on [{name}] which does not have the {nameof(OwnershipStatus.Transferable)} flag set!"); return false; @@ -539,13 +591,15 @@ namespace Unity.Netcode /// : The requires an ownership request via . /// : The is already processing an ownership request and ownership cannot be acquired at this time. /// : The does not have the flag set and ownership cannot be acquired. + /// : The has the flag set and ownership cannot be acquired. /// public enum OwnershipPermissionsFailureStatus { Locked, RequestRequired, RequestInProgress, - NotTransferrable + NotTransferrable, + SessionOwnerOnly } /// @@ -567,6 +621,7 @@ namespace Unity.Netcode /// : The flag is not set on this /// : The current owner has locked ownership which means requests are not available at this time. /// : There is already a known request in progress. You can scan for ownership changes and try upon + /// : This object is marked as SessionOwnerOnly and therefore cannot be requested /// a change in ownership or just try again after a specific period of time or no longer attempt to request ownership. /// public enum OwnershipRequestStatus @@ -576,6 +631,7 @@ namespace Unity.Netcode RequestRequiredNotSet, Locked, RequestInProgress, + SessionOwnerOnly, } /// @@ -588,6 +644,7 @@ namespace Unity.Netcode /// : The flag is not set on this /// : The current owner has locked ownership which means requests are not available at this time. /// : There is already a known request in progress. You can scan for ownership changes and try upon + /// : This object can only belong the the session owner and so cannot be requested /// a change in ownership or just try again after a specific period of time or no longer attempt to request ownership. /// /// @@ -617,6 +674,12 @@ namespace Unity.Netcode return OwnershipRequestStatus.RequestInProgress; } + // Exit early if it has the SessionOwner flag + if (IsOwnershipSessionOwner) + { + return OwnershipRequestStatus.SessionOwnerOnly; + } + // Otherwise, send the request ownership message var changeOwnership = new ChangeOwnershipMessage { @@ -673,7 +736,7 @@ namespace Unity.Netcode { response = OwnershipRequestResponseStatus.RequestInProgress; } - else if (!IsOwnershipRequestRequired && !IsOwnershipTransferable) + else if (!(IsOwnershipRequestRequired || IsOwnershipTransferable) || IsOwnershipSessionOwner) { response = OwnershipRequestResponseStatus.CannotRequest; } @@ -793,6 +856,12 @@ namespace Unity.Netcode /// public bool SetOwnershipStatus(OwnershipStatus status, bool clearAndSet = false, OwnershipLockActions lockAction = OwnershipLockActions.None) { + if (status.HasFlag(OwnershipStatus.SessionOwner) && !NetworkManager.LocalClient.IsSessionOwner) + { + NetworkLog.LogWarning("Only the session owner is allowed to set the ownership status to session owner only."); + return false; + } + // If it already has the flag do nothing if (!clearAndSet && Ownership.HasFlag(status)) { @@ -804,13 +873,25 @@ namespace Unity.Netcode Ownership = OwnershipStatus.None; } - // Faster to just OR a None status than to check - // if it is !None before "OR'ing". - Ownership |= status; - - if (lockAction != OwnershipLockActions.None) + if (status.HasFlag(OwnershipStatus.SessionOwner)) { - SetOwnershipLock(lockAction == OwnershipLockActions.SetAndLock); + Ownership = OwnershipStatus.SessionOwner; + } + else if (Ownership.HasFlag(OwnershipStatus.SessionOwner)) + { + NetworkLog.LogWarning("No other ownership statuses may be set while SessionOwner is set."); + return false; + } + else + { + // Faster to just OR a None status than to check + // if it is !None before "OR'ing". + Ownership |= status; + + if (lockAction != OwnershipLockActions.None) + { + SetOwnershipLock(lockAction == OwnershipLockActions.SetAndLock); + } } SendOwnershipStatusUpdate(); @@ -1586,7 +1667,7 @@ namespace Unity.Netcode // DANGO-TODO: Review over don't destroy with owner being set but DistributeOwnership not being set if (NetworkManager.LogLevel == LogLevel.Developer) { - NetworkLog.LogWarning("DANGO-TODO: Review over don't destroy with owner being set but DistributeOwnership not being set. For now, if the NetworkObject does not destroy with the owner it will automatically set DistributeOwnership."); + NetworkLog.LogWarning("DANGO-TODO: Review over don't destroy with owner being set but DistributeOwnership not being set. For now, if the NetworkObject does not destroy with the owner it will set ownership to SessionOwner."); } } } @@ -1964,12 +2045,14 @@ namespace Unity.Netcode internal bool InternalTrySetParent(NetworkObject parent, bool worldPositionStays = true) { - if (parent != null && (IsSpawned ^ parent.IsSpawned)) + if (parent != null && (IsSpawned ^ parent.IsSpawned) && NetworkManager != null && !NetworkManager.ShutdownInProgress) { - if (NetworkManager != null && !NetworkManager.ShutdownInProgress) + if (NetworkManager.LogLevel <= LogLevel.Developer) { - return false; + var nameOfNotSpawnedObject = IsSpawned ? $" the parent ({parent.name})" : $"the child ({name})"; + NetworkLog.LogWarning($"Parenting failed because {nameOfNotSpawnedObject} is not spawned!"); } + return false; } m_CachedWorldPositionStays = worldPositionStays; @@ -2892,7 +2975,7 @@ namespace Unity.Netcode SyncObservers = syncObservers, Observers = syncObservers ? Observers.ToArray() : null, NetworkSceneHandle = NetworkSceneHandle, - Hash = HostCheckForGlobalObjectIdHashOverride(), + Hash = CheckForGlobalObjectIdHashOverride(), OwnerObject = this, TargetClientId = targetClientId }; @@ -3244,14 +3327,15 @@ namespace Unity.Netcode } /// - /// Only applies to Host mode. + /// Client-Server: Only applies to spawn authority (i.e. Server) + /// Distributed Authority: Applies to all clients since they all have spawn authority. /// Will return the registered source NetworkPrefab's GlobalObjectIdHash if one exists. /// Server and Clients will always return the NetworkObject's GlobalObjectIdHash. /// - /// - internal uint HostCheckForGlobalObjectIdHashOverride() + /// appropriate hash value + internal uint CheckForGlobalObjectIdHashOverride() { - if (NetworkManager.IsServer) + if (NetworkManager.IsServer || NetworkManager.DistributedAuthorityMode) { if (NetworkManager.PrefabHandler.ContainsHandler(this)) { diff --git a/Runtime/Core/NetworkObjectRefreshTool.cs b/Runtime/Core/NetworkObjectRefreshTool.cs index 63d48e9..5309377 100644 --- a/Runtime/Core/NetworkObjectRefreshTool.cs +++ b/Runtime/Core/NetworkObjectRefreshTool.cs @@ -11,7 +11,7 @@ using UnityEngine.SceneManagement; namespace Unity.Netcode { /// - /// This is a helper tool to update all in-scene placed instances of a prefab that + /// This is a helper tool to update all in-scene placed instances of a prefab that /// originally did not have a NetworkObject component but one was added to the prefab /// later. /// diff --git a/Runtime/Messaging/ILPPMessageProvider.cs b/Runtime/Messaging/ILPPMessageProvider.cs index b7f90f6..4e697ac 100644 --- a/Runtime/Messaging/ILPPMessageProvider.cs +++ b/Runtime/Messaging/ILPPMessageProvider.cs @@ -16,7 +16,7 @@ namespace Unity.Netcode /// /// Enum representing the different types of messages that can be sent over the network. /// The values cannot be changed, as they are used to serialize and deserialize messages. - /// Adding new messages should be done by adding new values to the end of the enum + /// Adding new messages should be done by adding new values to the end of the enum /// using the next free value. /// /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/Runtime/Messaging/Messages/ChangeOwnershipMessage.cs b/Runtime/Messaging/Messages/ChangeOwnershipMessage.cs index d418789..998e84d 100644 --- a/Runtime/Messaging/Messages/ChangeOwnershipMessage.cs +++ b/Runtime/Messaging/Messages/ChangeOwnershipMessage.cs @@ -17,7 +17,7 @@ namespace Unity.Netcode /// /// When requesting, RequestClientId is the requestor. /// When approving, RequestClientId is the owner that approved. - /// When responding (only for denied), RequestClientId is the requestor + /// When responding (only for denied), RequestClientId is the requestor /// internal ulong RequestClientId; internal int ClientIdCount; @@ -272,7 +272,7 @@ namespace Unity.Netcode networkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.Reliable, clientId); } } - // If the NetworkObject is not visible to the DAHost client, then exit early + // If the NetworkObject is not visible to the DAHost client, then exit early if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId)) { return; @@ -294,7 +294,7 @@ namespace Unity.Netcode } /// - /// Handle the + /// Handle the extended distributed authority ownership updates /// /// private void HandleExtendedOwnershipUpdate(ref NetworkContext context) @@ -332,8 +332,8 @@ namespace Unity.Netcode // Sanity check that we are not sending duplicated change ownership messages if (networkObject.OwnerClientId == OwnerClientId) { - UnityEngine.Debug.LogError($"Unnecessary ownership changed message for {NetworkObjectId}."); - // Ignore the message + // Log error and then ignore the message + UnityEngine.Debug.LogError($"Client-{context.SenderId} ({RequestClientId}) sent unnecessary ownership changed message for {NetworkObjectId}."); return; } @@ -351,10 +351,10 @@ namespace Unity.Netcode networkObject.InvokeBehaviourOnLostOwnership(); } - // If in distributed authority mode + // If in distributed authority mode if (networkManager.DistributedAuthorityMode) { - // Always update the network properties in distributed authority mode + // Always update the network properties in distributed authority mode for (int i = 0; i < networkObject.ChildNetworkBehaviours.Count; i++) { networkObject.ChildNetworkBehaviours[i].UpdateNetworkProperties(); diff --git a/Runtime/Messaging/Messages/ClientConnectedMessage.cs b/Runtime/Messaging/Messages/ClientConnectedMessage.cs index ef7ef5f..0234bc8 100644 --- a/Runtime/Messaging/Messages/ClientConnectedMessage.cs +++ b/Runtime/Messaging/Messages/ClientConnectedMessage.cs @@ -55,19 +55,24 @@ namespace Unity.Netcode // Don't redistribute for the local instance if (ClientId != networkManager.LocalClientId) { + // Synchronize the client with spawned objects (relative to each client) + networkManager.SpawnManager.SynchronizeObjectsToNewlyJoinedClient(ClientId); + + // Keeping for reference in case the above doesn't resolve for hidden objects (theoretically it should) // Show any NetworkObjects that are: // - Hidden from the session owner // - Owned by this client // - Has NetworkObject.SpawnWithObservers set to true (the default) - if (!networkManager.LocalClient.IsSessionOwner) - { - networkManager.SpawnManager.ShowHiddenObjectsToNewlyJoinedClient(ClientId); - } + //if (!networkManager.LocalClient.IsSessionOwner) + //{ + // networkManager.SpawnManager.ShowHiddenObjectsToNewlyJoinedClient(ClientId); + //} - // We defer redistribution to the end of the NetworkUpdateStage.PostLateUpdate - networkManager.RedistributeToClient = true; - networkManager.ClientToRedistribute = ClientId; - networkManager.TickToRedistribute = networkManager.ServerTime.Tick + 20; + /// We defer redistribution to happen after NetworkShow has been invoked + /// + /// DANGO-TODO: Determine if this needs to be removed once the service handles object distribution + networkManager.RedistributeToClients = true; + networkManager.ClientsToRedistribute.Add(ClientId); } } } diff --git a/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs b/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs index 7b9a87f..5005c19 100644 --- a/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs +++ b/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs @@ -5,23 +5,38 @@ namespace Unity.Netcode { internal struct ServiceConfig : INetworkSerializable { - public uint Version; + public uint SessionVersion; public bool IsRestoredSession; public ulong CurrentSessionOwner; + public bool ServerRedistribution; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { if (serializer.IsWriter) { - BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), Version); + BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), SessionVersion); serializer.SerializeValue(ref IsRestoredSession); BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), CurrentSessionOwner); + + if (SessionVersion >= SessionConfig.ServerDistributionCompatible) + { + serializer.SerializeValue(ref ServerRedistribution); + } } else { - ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out Version); + ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out SessionVersion); serializer.SerializeValue(ref IsRestoredSession); ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out CurrentSessionOwner); + + if (SessionVersion >= SessionConfig.ServerDistributionCompatible) + { + serializer.SerializeValue(ref ServerRedistribution); + } + else + { + ServerRedistribution = false; + } } } } @@ -190,11 +205,13 @@ namespace Unity.Netcode if (receivedMessageVersion >= k_AddCMBServiceConfig) { reader.ReadNetworkSerializable(out ServiceConfig); + networkManager.SessionConfig = new SessionConfig(ServiceConfig); } else { reader.ReadValueSafe(out IsRestoredSession); ByteUnpacker.ReadValueBitPacked(reader, out CurrentSessionOwner); + networkManager.SessionConfig = new SessionConfig(SessionConfig.NoFeatureCompatibility); } } diff --git a/Runtime/Messaging/Messages/ConnectionRequestMessage.cs b/Runtime/Messaging/Messages/ConnectionRequestMessage.cs index d8e60d2..11aa4f3 100644 --- a/Runtime/Messaging/Messages/ConnectionRequestMessage.cs +++ b/Runtime/Messaging/Messages/ConnectionRequestMessage.cs @@ -7,31 +7,28 @@ namespace Unity.Netcode /// internal struct ClientConfig : INetworkSerializable { - /// - /// We start at version 1, where anything less than version 1 on the service side - /// is not bypass feature compatible. - /// - private const int k_BypassFeatureCompatible = 1; - public int Version => k_BypassFeatureCompatible; + public SessionConfig SessionConfig; + public int SessionVersion => (int)SessionConfig.SessionVersion; public uint TickRate; public bool EnableSceneManagement; // Only gets deserialized but should never be used unless testing - public int RemoteClientVersion; + public int RemoteClientSessionVersion; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { + // Clients always write if (serializer.IsWriter) { var writer = serializer.GetFastBufferWriter(); - BytePacker.WriteValueBitPacked(writer, Version); + BytePacker.WriteValueBitPacked(writer, SessionVersion); BytePacker.WriteValueBitPacked(writer, TickRate); writer.WriteValueSafe(EnableSceneManagement); } else { var reader = serializer.GetFastBufferReader(); - ByteUnpacker.ReadValueBitPacked(reader, out RemoteClientVersion); + ByteUnpacker.ReadValueBitPacked(reader, out RemoteClientSessionVersion); ByteUnpacker.ReadValueBitPacked(reader, out TickRate); reader.ReadValueSafe(out EnableSceneManagement); } @@ -40,6 +37,8 @@ namespace Unity.Netcode internal struct ConnectionRequestMessage : INetworkMessage { + internal const string InvalidSessionVersionMessage = "The client version is not compatible with the session version."; + // This version update is unidirectional (client to service) and version // handling occurs on the service side. This serialized data is never sent // to a host or server. @@ -47,7 +46,7 @@ namespace Unity.Netcode public int Version => k_SendClientConfigToService; public ulong ConfigHash; - public bool CMBServiceConnection; + public bool DistributedAuthority; public ClientConfig ClientConfig; public byte[] ConnectionData; @@ -72,7 +71,7 @@ namespace Unity.Netcode // END FORBIDDEN SEGMENT // ============================================================ - if (CMBServiceConnection) + if (DistributedAuthority) { writer.WriteNetworkSerializable(ClientConfig); } @@ -120,6 +119,11 @@ namespace Unity.Netcode // END FORBIDDEN SEGMENT // ============================================================ + if (networkManager.DAHost) + { + reader.ReadNetworkSerializable(out ClientConfig); + } + if (networkManager.NetworkConfig.ConnectionApproval) { if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(ConfigHash) + FastBufferWriter.GetWriteSize())) @@ -182,6 +186,17 @@ namespace Unity.Netcode var networkManager = (NetworkManager)context.SystemOwner; var senderId = context.SenderId; + // DAHost mocking the service logic to disconnect clients trying to connect with a lower session version + if (networkManager.DAHost) + { + if (ClientConfig.RemoteClientSessionVersion < networkManager.SessionConfig.SessionVersion) + { + //Disconnect with reason + networkManager.ConnectionManager.DisconnectClient(senderId, InvalidSessionVersionMessage); + return; + } + } + if (networkManager.ConnectionManager.PendingClients.TryGetValue(senderId, out PendingClient client)) { // Set to pending approval to prevent future connection requests from being approved diff --git a/Runtime/Messaging/Messages/CreateObjectMessage.cs b/Runtime/Messaging/Messages/CreateObjectMessage.cs index 6c0656b..02f4263 100644 --- a/Runtime/Messaging/Messages/CreateObjectMessage.cs +++ b/Runtime/Messaging/Messages/CreateObjectMessage.cs @@ -257,7 +257,7 @@ namespace Unity.Netcode { // DA - NGO CMB SERVICE NOTES: // (*** See above notes fist ***) - // If it is a player object freshly spawning and one or more clients all connect at the exact same time (i.e. received on effectively + // If it is a player object freshly spawning and one or more clients all connect at the exact same time (i.e. received on effectively // the same frame), then we need to check the observers list to make sure all players are visible upon first spawning. At a later date, // for area of interest we will need to have some form of follow up "observer update" message to cull out players not within each // player's AOI. diff --git a/Runtime/Messaging/Messages/NetworkTransformMessage.cs b/Runtime/Messaging/Messages/NetworkTransformMessage.cs index 56f25f2..cf4013f 100644 --- a/Runtime/Messaging/Messages/NetworkTransformMessage.cs +++ b/Runtime/Messaging/Messages/NetworkTransformMessage.cs @@ -128,7 +128,7 @@ namespace Unity.Netcode } else if (networkManager.DAHost) { - // Specific to distributed authority mode, the only sender of state updates will be the owner + // Specific to distributed authority mode, the only sender of state updates will be the owner ownerClientId = context.SenderId; } diff --git a/Runtime/Messaging/Messages/ParentSyncMessage.cs b/Runtime/Messaging/Messages/ParentSyncMessage.cs index bef5fe8..33caa7d 100644 --- a/Runtime/Messaging/Messages/ParentSyncMessage.cs +++ b/Runtime/Messaging/Messages/ParentSyncMessage.cs @@ -70,10 +70,6 @@ namespace Unity.Netcode public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) { var networkManager = (NetworkManager)context.SystemOwner; - if (!networkManager.IsClient) - { - return false; - } ByteUnpacker.ReadValueBitPacked(reader, out NetworkObjectId); reader.ReadValueSafe(out m_BitField); diff --git a/Runtime/Messaging/NetworkMessageManager.cs b/Runtime/Messaging/NetworkMessageManager.cs index 1850725..661fbd7 100644 --- a/Runtime/Messaging/NetworkMessageManager.cs +++ b/Runtime/Messaging/NetworkMessageManager.cs @@ -141,28 +141,6 @@ namespace Unity.Netcode { RegisterMessageType(type); } - -#if UNITY_EDITOR - if (EnableMessageOrderConsoleLog) - { - // DANGO-TODO: Remove this when we have some form of message type indices stability in place - // For now, just log the messages and their assigned types for reference purposes. - var networkManager = m_Owner as NetworkManager; - if (networkManager != null) - { - if (networkManager.DistributedAuthorityMode) - { - var messageListing = new StringBuilder(); - messageListing.AppendLine("NGO Message Index to Type Listing:"); - foreach (var message in m_MessageTypes) - { - messageListing.AppendLine($"[{message.Value}][{message.Key.Name}]"); - } - Debug.Log(messageListing); - } - } - } -#endif } catch (Exception) { diff --git a/Runtime/Messaging/RpcTargets/ClientsAndHostRpcTarget.cs b/Runtime/Messaging/RpcTargets/ClientsAndHostRpcTarget.cs index 286b0b0..373e43f 100644 --- a/Runtime/Messaging/RpcTargets/ClientsAndHostRpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/ClientsAndHostRpcTarget.cs @@ -17,7 +17,8 @@ namespace Unity.Netcode // ClientsAndHost sends to everyone who runs any client logic // So if the server is a host, this target includes it (as hosts run client logic) // If the server is not a host, this target leaves it out, ergo the selection of NotServer. - if (behaviour.NetworkManager.ServerIsHost) + // If we are in distributed authority mode and connected to a service, then send to all clients. + if (behaviour.NetworkManager.ServerIsHost || (m_NetworkManager.DistributedAuthorityMode && m_NetworkManager.CMBServiceConnection)) { m_UnderlyingTarget = behaviour.RpcTarget.Everyone; } diff --git a/Runtime/Messaging/RpcTargets/NotOwnerRpcTarget.cs b/Runtime/Messaging/RpcTargets/NotOwnerRpcTarget.cs index e4f64f0..348c1af 100644 --- a/Runtime/Messaging/RpcTargets/NotOwnerRpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/NotOwnerRpcTarget.cs @@ -4,12 +4,14 @@ namespace Unity.Netcode { private IGroupRpcTarget m_GroupSendTarget; private ServerRpcTarget m_ServerRpcTarget; + private NotAuthorityRpcTarget m_NotAuthorityRpcTarget; private LocalSendRpcTarget m_LocalSendRpcTarget; public override void Dispose() { m_ServerRpcTarget.Dispose(); m_LocalSendRpcTarget.Dispose(); + m_NotAuthorityRpcTarget.Dispose(); if (m_GroupSendTarget != null) { m_GroupSendTarget.Target.Dispose(); @@ -19,6 +21,13 @@ namespace Unity.Netcode internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams) { + // Not owner is the same as not authority in distributed authority mode + if (m_NetworkManager.DistributedAuthorityMode) + { + m_NotAuthorityRpcTarget.Send(behaviour, ref message, delivery, rpcParams); + return; + } + if (m_GroupSendTarget == null) { if (behaviour.IsServer) @@ -86,6 +95,7 @@ namespace Unity.Netcode { m_ServerRpcTarget = new ServerRpcTarget(manager); m_LocalSendRpcTarget = new LocalSendRpcTarget(manager); + m_NotAuthorityRpcTarget = new NotAuthorityRpcTarget(manager); } } } diff --git a/Runtime/Messaging/RpcTargets/NotServerRpcTarget.cs b/Runtime/Messaging/RpcTargets/NotServerRpcTarget.cs index 30b745e..3ac0b23 100644 --- a/Runtime/Messaging/RpcTargets/NotServerRpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/NotServerRpcTarget.cs @@ -51,7 +51,13 @@ namespace Unity.Netcode continue; } - if (clientId == behaviour.NetworkManager.LocalClientId) + // If we are in distributed authority mode and connected to the service, then we exclude the owner/authority from the list + if (m_NetworkManager.DistributedAuthorityMode && m_NetworkManager.CMBServiceConnection && clientId == behaviour.OwnerClientId) + { + continue; + } + + if (clientId == m_NetworkManager.LocalClientId) { m_LocalSendRpcTarget.Send(behaviour, ref message, delivery, rpcParams); continue; diff --git a/Runtime/Messaging/RpcTargets/OwnerRpcTarget.cs b/Runtime/Messaging/RpcTargets/OwnerRpcTarget.cs index 7c78294..e22c588 100644 --- a/Runtime/Messaging/RpcTargets/OwnerRpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/OwnerRpcTarget.cs @@ -5,9 +5,12 @@ namespace Unity.Netcode private IIndividualRpcTarget m_UnderlyingTarget; private LocalSendRpcTarget m_LocalRpcTarget; private ServerRpcTarget m_ServerRpcTarget; + private AuthorityRpcTarget m_AuthorityRpcTarget; public override void Dispose() { + m_AuthorityRpcTarget.Dispose(); + m_ServerRpcTarget.Dispose(); m_LocalRpcTarget.Dispose(); if (m_UnderlyingTarget != null) { @@ -18,6 +21,13 @@ namespace Unity.Netcode internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams) { + // Sending to owner is the same as sending to authority in distributed authority mode + if (m_NetworkManager.DistributedAuthorityMode) + { + m_AuthorityRpcTarget.Send(behaviour, ref message, delivery, rpcParams); + return; + } + if (behaviour.OwnerClientId == behaviour.NetworkManager.LocalClientId) { m_LocalRpcTarget.Send(behaviour, ref message, delivery, rpcParams); @@ -49,6 +59,7 @@ namespace Unity.Netcode { m_LocalRpcTarget = new LocalSendRpcTarget(manager); m_ServerRpcTarget = new ServerRpcTarget(manager); + m_AuthorityRpcTarget = new AuthorityRpcTarget(manager); } } } diff --git a/Runtime/Messaging/RpcTargets/RpcTarget.cs b/Runtime/Messaging/RpcTargets/RpcTarget.cs index c5706a8..2864205 100644 --- a/Runtime/Messaging/RpcTargets/RpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/RpcTarget.cs @@ -79,9 +79,28 @@ namespace Unity.Netcode SpecifiedInParams } + /// + /// This parameter configures a performance optimization. This optimization is not valid in all situations.
+ /// Because BaseRpcTarget is a managed type, allocating a new one is expensive, as it puts pressure on the garbage collector. + ///
+ /// + /// When using a allocation type for the RPC target(s):
+ /// You typically don't need to worry about persisting the generated. + /// When using a allocation type for the RPC target(s):
+ /// You will want to use , which returns , during initialization (i.e. ) and it to a property.
+ /// Then, When invoking the RPC, you would use your which is a persisted allocation of a given set of client identifiers. + /// !! Important !!
+ /// You will want to invoke of any persisted properties created via when despawning or destroying the associated component's . Not doing so will result in small memory leaks. + ///
public enum RpcTargetUse { + /// + /// Creates a temporary used for the frame an decorated method is invoked. + /// Temp, + /// + /// Creates a persisted that does not change and will persist until is called. + /// Persistent } diff --git a/Runtime/Messaging/RpcTargets/ServerRpcTarget.cs b/Runtime/Messaging/RpcTargets/ServerRpcTarget.cs index 8ad53fb..87bfbfb 100644 --- a/Runtime/Messaging/RpcTargets/ServerRpcTarget.cs +++ b/Runtime/Messaging/RpcTargets/ServerRpcTarget.cs @@ -1,8 +1,10 @@ +using Unity.Collections; namespace Unity.Netcode { internal class ServerRpcTarget : BaseRpcTarget { protected BaseRpcTarget m_UnderlyingTarget; + protected ProxyRpcTarget m_ProxyRpcTarget; public override void Dispose() { @@ -11,13 +13,62 @@ namespace Unity.Netcode m_UnderlyingTarget.Dispose(); m_UnderlyingTarget = null; } + + if (m_ProxyRpcTarget != null) + { + m_ProxyRpcTarget.Dispose(); + m_ProxyRpcTarget = null; + } } internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams) { + // For distributed authority the "server" is considered the authority of the object if (behaviour.NetworkManager.DistributedAuthorityMode && behaviour.NetworkManager.CMBServiceConnection) { - UnityEngine.Debug.LogWarning("[Invalid Target] There is no server to send to when in Distributed Authority mode!"); + // If the local instance is the owner, then invoke the message locally on this behaviour + if (behaviour.IsOwner) + { + var context = new NetworkContext + { + SenderId = m_NetworkManager.LocalClientId, + Timestamp = m_NetworkManager.RealTimeProvider.RealTimeSinceStartup, + SystemOwner = m_NetworkManager, + // header information isn't valid since it's not a real message. + // RpcMessage doesn't access this stuff so it's just left empty. + Header = new NetworkMessageHeader(), + SerializedHeaderSize = 0, + MessageSize = 0 + }; + using var tempBuffer = new FastBufferReader(message.WriteBuffer, Allocator.None); + message.ReadBuffer = tempBuffer; + message.Handle(ref context); + // If enabled, then add the RPC metrics for this +#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE + int length = tempBuffer.Length; + if (NetworkBehaviour.__rpc_name_table[behaviour.GetType()].TryGetValue(message.Metadata.NetworkRpcMethodId, out var rpcMethodName)) + { + m_NetworkManager.NetworkMetrics.TrackRpcSent( + m_NetworkManager.LocalClientId, + behaviour.NetworkObject, + rpcMethodName, + behaviour.__getTypeName(), + length); + } +#endif + } + else // Otherwise, send a proxied message to the owner of the object + { + if (m_ProxyRpcTarget == null) + { + m_ProxyRpcTarget = new ProxyRpcTarget(behaviour.OwnerClientId, m_NetworkManager); + } + else + { + m_ProxyRpcTarget.SetClientId(behaviour.OwnerClientId); + } + m_ProxyRpcTarget.Send(behaviour, ref message, delivery, rpcParams); + } return; } diff --git a/Runtime/NetworkVariable/Collections/NetworkList.cs b/Runtime/NetworkVariable/Collections/NetworkList.cs index 203632c..4a34997 100644 --- a/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -24,7 +24,6 @@ namespace Unity.Netcode /// The callback to be invoked when the list gets changed ///
public event OnListChangedDelegate OnListChanged; - internal override NetworkVariableType Type => NetworkVariableType.NetworkList; /// /// Constructor method for @@ -50,6 +49,11 @@ namespace Unity.Netcode } } + ~NetworkList() + { + Dispose(); + } + /// public override void ResetDirty() { @@ -131,20 +135,6 @@ namespace Unity.Netcode /// public override void WriteField(FastBufferWriter writer) { - if (m_NetworkManager.DistributedAuthorityMode) - { - writer.WriteValueSafe(NetworkVariableSerialization.Serializer.Type); - if (NetworkVariableSerialization.Serializer.Type == NetworkVariableType.Unmanaged) - { - // Write the size of the unmanaged serialized type as it has a fixed size. This allows the CMB runtime to correctly read the unmanged type. - var placeholder = new T(); - var startPos = writer.Position; - NetworkVariableSerialization.Serializer.Write(writer, ref placeholder); - var size = writer.Position - startPos; - writer.Seek(startPos); - BytePacker.WriteValueBitPacked(writer, size); - } - } writer.WriteValueSafe((ushort)m_List.Length); for (int i = 0; i < m_List.Length; i++) { @@ -156,15 +146,6 @@ namespace Unity.Netcode public override void ReadField(FastBufferReader reader) { m_List.Clear(); - if (m_NetworkManager.DistributedAuthorityMode) - { - SerializationTools.ReadType(reader, NetworkVariableSerialization.Serializer); - // Collection item type is used by the DA server, drop value here. - if (NetworkVariableSerialization.Serializer.Type == NetworkVariableType.Unmanaged) - { - ByteUnpacker.ReadValueBitPacked(reader, out int _); - } - } reader.ReadValueSafe(out ushort count); for (int i = 0; i < count; i++) { @@ -624,8 +605,16 @@ namespace Unity.Netcode /// public override void Dispose() { - m_List.Dispose(); - m_DirtyEvents.Dispose(); + if (m_List.IsCreated) + { + m_List.Dispose(); + } + + if (m_DirtyEvents.IsCreated) + { + m_DirtyEvents.Dispose(); + } + base.Dispose(); } } diff --git a/Runtime/NetworkVariable/NetworkVariable.cs b/Runtime/NetworkVariable/NetworkVariable.cs index 16ca42a..c712a90 100644 --- a/Runtime/NetworkVariable/NetworkVariable.cs +++ b/Runtime/NetworkVariable/NetworkVariable.cs @@ -45,8 +45,6 @@ namespace Unity.Netcode NetworkVariableSerialization.Duplicate(m_InternalValue, ref m_PreviousValue); } - internal override NetworkVariableType Type => NetworkVariableType.Value; - /// /// Constructor for /// @@ -92,7 +90,7 @@ namespace Unity.Netcode // The introduction of standard .NET collections caused an issue with permissions since there is no way to detect changes in the // collection without doing a full comparison. While this approach does consume more memory per collection instance, it is the // lowest risk approach to resolving the issue where a client with no write permissions could make changes to a collection locally - // which can cause a myriad of issues. + // which can cause a myriad of issues. private protected T m_InternalOriginalValue; private protected T m_PreviousValue; @@ -181,19 +179,26 @@ namespace Unity.Netcode } m_IsDisposed = true; + // Dispose the internal value if (m_InternalValue is IDisposable internalValueDisposable) { internalValueDisposable.Dispose(); } - m_InternalValue = default; + + // Dispose the internal original value + if (m_InternalOriginalValue is IDisposable internalOriginalValueDisposable) + { + internalOriginalValueDisposable.Dispose(); + } m_InternalOriginalValue = default; + + // Dispose the previous value if there is one if (m_HasPreviousValue && m_PreviousValue is IDisposable previousValueDisposable) { m_HasPreviousValue = false; previousValueDisposable.Dispose(); } - m_PreviousValue = default; base.Dispose(); @@ -298,7 +303,7 @@ namespace Unity.Netcode /// This should be always invoked (client & server) to assure the previous values are set /// !! IMPORTANT !! /// When a server forwards delta updates to connected clients, it needs to preserve the previous dirty value(s) - /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked + /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked /// after it is done forwarding the deltas at the end of the method. ///
internal override void PostDeltaRead() diff --git a/Runtime/NetworkVariable/NetworkVariableBase.cs b/Runtime/NetworkVariable/NetworkVariableBase.cs index 8802397..537d3eb 100644 --- a/Runtime/NetworkVariable/NetworkVariableBase.cs +++ b/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -35,8 +35,6 @@ namespace Unity.Netcode private NetworkManager m_InternalNetworkManager; - internal virtual NetworkVariableType Type => NetworkVariableType.Unknown; - internal string GetWritePermissionError() { return $"|Client-{m_NetworkManager.LocalClientId}|{m_NetworkBehaviour.name}|{Name}| Write permissions ({WritePerm}) for this client instance is not allowed!"; @@ -351,7 +349,7 @@ namespace Unity.Netcode /// This should be always invoked (client & server) to assure the previous values are set /// !! IMPORTANT !! /// When a server forwards delta updates to connected clients, it needs to preserve the previous dirty value(s) - /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked + /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked /// after it is done forwarding the deltas at the end of the method. ///
internal virtual void PostDeltaRead() diff --git a/Runtime/NetworkVariable/NetworkVariableTypes.cs b/Runtime/NetworkVariable/NetworkVariableTypes.cs deleted file mode 100644 index d8b6912..0000000 --- a/Runtime/NetworkVariable/NetworkVariableTypes.cs +++ /dev/null @@ -1,40 +0,0 @@ -#if UNITY_EDITOR -#endif - -namespace Unity.Netcode -{ - /// - /// Enum representing the different types of Network Variables that can be sent over the network. - /// The values cannot be changed, as they are used to serialize and deserialize variables on the DA server. - /// Adding new variables should be done by adding new values to the end of the enum - /// using the next free value. - /// - /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - /// Add any new Variable types to this table at the END with incremented index value - /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - internal enum NetworkVariableType : byte - { - /// - /// Value - /// Used for all of the basic NetworkVariables that contain a single value - /// - Value = 0, - /// - /// For any type that is not known at runtime - /// - Unknown = 1, - /// - /// NetworkList - /// - NetworkList = 2, - - // The following types are valid types inside of NetworkVariable collections - Short = 11, - UShort = 12, - Int = 13, - UInt = 14, - Long = 15, - ULong = 16, - Unmanaged = 17, - } -} diff --git a/Runtime/NetworkVariable/NetworkVariableTypes.cs.meta b/Runtime/NetworkVariable/NetworkVariableTypes.cs.meta deleted file mode 100644 index 4206dbc..0000000 --- a/Runtime/NetworkVariable/NetworkVariableTypes.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: df4a4005f1c842669f94a404019400ed -timeCreated: 1718292058 \ No newline at end of file diff --git a/Runtime/NetworkVariable/Serialization/FallbackSerializer.cs b/Runtime/NetworkVariable/Serialization/FallbackSerializer.cs index 0b1b2c1..5e85574 100644 --- a/Runtime/NetworkVariable/Serialization/FallbackSerializer.cs +++ b/Runtime/NetworkVariable/Serialization/FallbackSerializer.cs @@ -14,9 +14,6 @@ namespace Unity.Netcode /// internal class FallbackSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.Unknown; - public bool IsDistributedAuthorityOptimized => true; - private void ThrowArgumentError() { throw new ArgumentException($"Serialization has not been generated for type {typeof(T).FullName}. This can be addressed by adding a [{nameof(GenerateSerializationForGenericParameterAttribute)}] to your generic class that serializes this value (if you are using one), adding [{nameof(GenerateSerializationForTypeAttribute)}(typeof({typeof(T).FullName})] to the class or method that is attempting to serialize it, or creating a field on a {nameof(NetworkBehaviour)} of type {nameof(NetworkVariable)}. If this error continues to appear after doing one of those things and this is a type you can change, then either implement {nameof(INetworkSerializable)} or mark it as serializable by memcpy by adding {nameof(INetworkSerializeByMemcpy)} to its interface list to enable automatic serialization generation. If not, assign serialization code to {nameof(UserNetworkVariableSerialization)}.{nameof(UserNetworkVariableSerialization.WriteValue)}, {nameof(UserNetworkVariableSerialization)}.{nameof(UserNetworkVariableSerialization.ReadValue)}, and {nameof(UserNetworkVariableSerialization)}.{nameof(UserNetworkVariableSerialization.DuplicateValue)}, or if it's serializable by memcpy (contains no pointers), wrap it in {typeof(ForceNetworkSerializeByMemcpy<>).Name}."); @@ -82,11 +79,6 @@ namespace Unity.Netcode } UserNetworkVariableSerialization.DuplicateValue(value, ref duplicatedValue); } - - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) => ThrowArgumentError(); - public void ReadDistributedAuthority(FastBufferReader reader, ref T value) => ThrowArgumentError(); - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => ThrowArgumentError(); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => ThrowArgumentError(); } // RuntimeAccessModifiersILPP will make this `public` diff --git a/Runtime/NetworkVariable/Serialization/INetworkVariableSerializer.cs b/Runtime/NetworkVariable/Serialization/INetworkVariableSerializer.cs index 571d1dc..d515c0c 100644 --- a/Runtime/NetworkVariable/Serialization/INetworkVariableSerializer.cs +++ b/Runtime/NetworkVariable/Serialization/INetworkVariableSerializer.cs @@ -2,28 +2,8 @@ using Unity.Collections; namespace Unity.Netcode { - /// - /// Interface used by NetworkVariables to serialize them with additional information for the DA runtime - /// - /// /// - internal interface IDistributedAuthoritySerializer - { - /// - /// The Type tells the DA server how to parse this type. - /// The user should never be able to override this value, as it is meaningful for the DA server - /// - public NetworkVariableType Type { get; } - public bool IsDistributedAuthorityOptimized { get; } - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value); - public void ReadDistributedAuthority(FastBufferReader reader, ref T value); - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value); - } - - - /// - internal interface INetworkVariableSerializer : IDistributedAuthoritySerializer + internal interface INetworkVariableSerializer { // Write has to be taken by ref here because of INetworkSerializable // Open Instance Delegates (pointers to methods without an instance attached to them) diff --git a/Runtime/NetworkVariable/Serialization/NetworkVariableSerialization.cs b/Runtime/NetworkVariable/Serialization/NetworkVariableSerialization.cs index bc0f79f..8401df8 100644 --- a/Runtime/NetworkVariable/Serialization/NetworkVariableSerialization.cs +++ b/Runtime/NetworkVariable/Serialization/NetworkVariableSerialization.cs @@ -14,8 +14,6 @@ namespace Unity.Netcode { internal static INetworkVariableSerializer Serializer = new FallbackSerializer(); - internal static bool IsDistributedAuthority => NetworkManager.IsDistributedAuthority; - /// /// A callback to check if two values are equal. /// @@ -53,20 +51,7 @@ namespace Unity.Netcode /// public static void Write(FastBufferWriter writer, ref T value) { - if (IsDistributedAuthority) - { -#if DEVELOPMENT_BUILD || UNITY_EDITOR - if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized) - { - NetworkManager.LogSerializedTypeNotOptimized(); - } -#endif - Serializer.WriteDistributedAuthority(writer, ref value); - } - else - { - Serializer.Write(writer, ref value); - } + Serializer.Write(writer, ref value); } /// @@ -91,14 +76,7 @@ namespace Unity.Netcode /// public static void Read(FastBufferReader reader, ref T value) { - if (IsDistributedAuthority) - { - Serializer.ReadDistributedAuthority(reader, ref value); - } - else - { - Serializer.Read(reader, ref value); - } + Serializer.Read(reader, ref value); } /// @@ -120,20 +98,7 @@ namespace Unity.Netcode /// public static void WriteDelta(FastBufferWriter writer, ref T value, ref T previousValue) { - if (IsDistributedAuthority) - { -#if DEVELOPMENT_BUILD || UNITY_EDITOR - if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized) - { - NetworkManager.LogSerializedTypeNotOptimized(); - } -#endif - Serializer.WriteDeltaDistributedAuthority(writer, ref value, ref previousValue); - } - else - { - Serializer.WriteDelta(writer, ref value, ref previousValue); - } + Serializer.WriteDelta(writer, ref value, ref previousValue); } /// @@ -158,14 +123,7 @@ namespace Unity.Netcode /// public static void ReadDelta(FastBufferReader reader, ref T value) { - if (IsDistributedAuthority) - { - Serializer.ReadDeltaDistributedAuthority(reader, ref value); - } - else - { - Serializer.ReadDelta(reader, ref value); - } + Serializer.ReadDelta(reader, ref value); } /// diff --git a/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs b/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs index 9f5a104..49e7e5e 100644 --- a/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs +++ b/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs @@ -10,21 +10,6 @@ namespace Unity.Netcode /// internal class ShortSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.Short; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref short value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref short value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref short value, ref short previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref short value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref short value) { BytePacker.WriteValueBitPacked(writer, value); @@ -61,20 +46,6 @@ namespace Unity.Netcode /// internal class UshortSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.UShort; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref ushort value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref ushort value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref ushort value, ref ushort previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref ushort value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref ushort value) { BytePacker.WriteValueBitPacked(writer, value); @@ -111,20 +82,6 @@ namespace Unity.Netcode /// internal class IntSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.Int; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref int value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref int value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref int value, ref int previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref int value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref int value) { BytePacker.WriteValueBitPacked(writer, value); @@ -161,20 +118,6 @@ namespace Unity.Netcode /// internal class UintSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.UInt; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref uint value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref uint value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref uint value, ref uint previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref uint value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref uint value) { BytePacker.WriteValueBitPacked(writer, value); @@ -211,20 +154,6 @@ namespace Unity.Netcode ///
internal class LongSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.Long; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref long value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref long value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref long value, ref long previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref long value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref long value) { BytePacker.WriteValueBitPacked(writer, value); @@ -261,21 +190,6 @@ namespace Unity.Netcode /// internal class UlongSerializer : INetworkVariableSerializer { - public NetworkVariableType Type => NetworkVariableType.ULong; - public bool IsDistributedAuthorityOptimized => true; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref ulong value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref ulong value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref ulong value, ref ulong previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref ulong value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref ulong value) { BytePacker.WriteValueBitPacked(writer, value); @@ -317,21 +231,6 @@ namespace Unity.Netcode /// internal class UnmanagedTypeSerializer : INetworkVariableSerializer where T : unmanaged { - public NetworkVariableType Type => NetworkVariableType.Unmanaged; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref T value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref T value) { writer.WriteUnmanagedSafe(value); @@ -365,20 +264,6 @@ namespace Unity.Netcode internal class ListSerializer : INetworkVariableSerializer> { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref List value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref List value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref List value, ref List previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref List value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref List value) { var isNull = value == null; @@ -468,20 +353,6 @@ namespace Unity.Netcode internal class HashSetSerializer : INetworkVariableSerializer> where T : IEquatable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref HashSet value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref HashSet value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref HashSet value, ref HashSet previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref HashSet value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref HashSet value) { var isNull = value == null; @@ -563,20 +434,6 @@ namespace Unity.Netcode internal class DictionarySerializer : INetworkVariableSerializer> where TKey : IEquatable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref Dictionary value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref Dictionary value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref Dictionary value, ref Dictionary previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref Dictionary value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref Dictionary value) { var isNull = value == null; @@ -659,20 +516,6 @@ namespace Unity.Netcode internal class UnmanagedArraySerializer : INetworkVariableSerializer> where T : unmanaged { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray value, ref NativeArray previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref NativeArray value) { writer.WriteUnmanagedSafe(value); @@ -718,20 +561,6 @@ namespace Unity.Netcode #if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT internal class UnmanagedListSerializer : INetworkVariableSerializer> where T : unmanaged { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList value, ref NativeList previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref NativeList value) { writer.WriteUnmanagedSafe(value); @@ -775,21 +604,6 @@ namespace Unity.Netcode internal class NativeHashSetSerializer : INetworkVariableSerializer> where T : unmanaged, IEquatable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeHashSet value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeHashSet value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeHashSet value, ref NativeHashSet previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeHashSet value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref NativeHashSet value) { writer.WriteValueSafe(value); @@ -835,21 +649,6 @@ namespace Unity.Netcode where TKey : unmanaged, IEquatable where TVal : unmanaged { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeHashMap value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeHashMap value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeHashMap value, ref NativeHashMap previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeHashMap value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref NativeHashMap value) { writer.WriteValueSafe(value); @@ -897,21 +696,6 @@ namespace Unity.Netcode /// internal class FixedStringSerializer : INetworkVariableSerializer where T : unmanaged, INativeList, IUTF8Bytes { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref T value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref T value) { writer.WriteValueSafe(value); @@ -1019,20 +803,6 @@ namespace Unity.Netcode /// internal class FixedStringArraySerializer : INetworkVariableSerializer> where T : unmanaged, INativeList, IUTF8Bytes { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray value, ref NativeArray previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref NativeArray value) { writer.WriteValueSafe(value); @@ -1083,21 +853,6 @@ namespace Unity.Netcode /// internal class FixedStringListSerializer : INetworkVariableSerializer> where T : unmanaged, INativeList, IUTF8Bytes { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList value, ref NativeList previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref NativeList value) { writer.WriteValueSafe(value); @@ -1145,21 +900,6 @@ namespace Unity.Netcode /// internal class UnmanagedNetworkSerializableSerializer : INetworkVariableSerializer where T : unmanaged, INetworkSerializable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref T value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref T value) { var bufferSerializer = new BufferSerializer(new BufferSerializerWriter(writer)); @@ -1212,20 +952,6 @@ namespace Unity.Netcode /// internal class UnmanagedNetworkSerializableArraySerializer : INetworkVariableSerializer> where T : unmanaged, INetworkSerializable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeArray value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeArray value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeArray value, ref NativeArray previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeArray value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref NativeArray value) { writer.WriteNetworkSerializable(value); @@ -1276,21 +1002,6 @@ namespace Unity.Netcode /// internal class UnmanagedNetworkSerializableListSerializer : INetworkVariableSerializer> where T : unmanaged, INetworkSerializable { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref NativeList value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref NativeList value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref NativeList value, ref NativeList previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref NativeList value) => Read(reader, ref value); - public void Write(FastBufferWriter writer, ref NativeList value) { writer.WriteNetworkSerializable(value); @@ -1338,20 +1049,6 @@ namespace Unity.Netcode /// internal class ManagedNetworkSerializableSerializer : INetworkVariableSerializer where T : class, INetworkSerializable, new() { - public NetworkVariableType Type => NetworkVariableType.Value; - public bool IsDistributedAuthorityOptimized => false; - - public void WriteDistributedAuthority(FastBufferWriter writer, ref T value) - { - Write(writer, ref value); - } - - public void ReadDistributedAuthority(FastBufferReader reader, ref T value) - { - Read(reader, ref value); - } - public void WriteDeltaDistributedAuthority(FastBufferWriter writer, ref T value, ref T previousValue) => Write(writer, ref value); - public void ReadDeltaDistributedAuthority(FastBufferReader reader, ref T value) => Read(reader, ref value); public void Write(FastBufferWriter writer, ref T value) { var bufferSerializer = new BufferSerializer(new BufferSerializerWriter(writer)); diff --git a/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs b/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs deleted file mode 100644 index 50ea37d..0000000 --- a/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; - -namespace Unity.Netcode -{ - - internal static class SerializationTools - { - public delegate void WriteDelegate(FastBufferWriter writer, ref T value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteWithSize(WriteDelegate writeMethod, FastBufferWriter writer, ref T value) - { - var writePos = writer.Position; - // Note: This value can't be packed because we don't know how large it will be in advance - // we reserve space for it, then write the data, then come back and fill in the space - // to pack here, we'd have to write data to a temporary buffer and copy it in - which - // isn't worth possibly saving one byte if and only if the data is less than 63 bytes long... - // The way we do packing, any value > 63 in a ushort will use the full 2 bytes to represent. - writer.WriteValueSafe((ushort)0); - var startPos = writer.Position; - writeMethod(writer, ref value); - var size = writer.Position - startPos; - writer.Seek(writePos); - writer.WriteValueSafe((ushort)size); - writer.Seek(startPos + size); - } - - public delegate void ReadDelegate(FastBufferReader writer, ref T value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ReadWithSize(ReadDelegate readMethod, FastBufferReader reader, ref T value) - { - reader.ReadValueSafe(out ushort _); - readMethod(reader, ref value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteType(FastBufferWriter writer, NetworkVariableType type) => writer.WriteValueSafe(type); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ReadType(FastBufferReader reader, INetworkVariableSerializer serializer) - { - reader.ReadValueSafe(out NetworkVariableType type); - if (type != serializer.Type) - { - throw new SerializationException(); - } - } - - - } - -} diff --git a/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs.meta b/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs.meta deleted file mode 100644 index 006046f..0000000 --- a/Runtime/NetworkVariable/Serialization/VariableSerializationTools.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 52a4ce368df54b0a8887c08f3402bcd3 -timeCreated: 1718300602 \ No newline at end of file diff --git a/Runtime/SceneManagement/NetworkSceneManager.cs b/Runtime/SceneManagement/NetworkSceneManager.cs index 6522200..8996dfc 100644 --- a/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/Runtime/SceneManagement/NetworkSceneManager.cs @@ -1081,14 +1081,19 @@ namespace Unity.Netcode } else { - var message = new SceneEventMessage + // Send to each individual client to assure only the in-scene placed NetworkObjects being observed by the client + // is serialized + foreach (var clientId in targetClientIds) { - EventData = sceneEvent, - }; - var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, targetClientIds); - NetworkManager.NetworkMetrics.TrackSceneEventSent(targetClientIds, (uint)SceneEventDataStore[sceneEventId].SceneEventType, SceneNameFromHash(SceneEventDataStore[sceneEventId].SceneHash), size); + sceneEvent.TargetClientId = clientId; + var message = new SceneEventMessage + { + EventData = sceneEvent, + }; + var size = NetworkManager.ConnectionManager.SendMessage(ref message, k_DeliveryType, clientId); + NetworkManager.NetworkMetrics.TrackSceneEventSent(clientId, (uint)sceneEvent.SceneEventType, SceneNameFromHash(sceneEvent.SceneHash), size); + } } - } /// @@ -1898,10 +1903,12 @@ namespace Unity.Netcode SendSceneEventData(sceneEventData.SceneEventId, NetworkManager.ConnectedClientsIds.Where(c => c != sessionOwner).ToArray()); m_IsSceneEventActive = false; + + sceneEventData.SceneEventType = SceneEventType.LoadComplete; //First, notify local server that the scene was loaded OnSceneEvent?.Invoke(new SceneEvent() { - SceneEventType = SceneEventType.LoadComplete, + SceneEventType = sceneEventData.SceneEventType, LoadSceneMode = sceneEventData.LoadSceneMode, SceneName = SceneNameFromHash(sceneEventData.SceneHash), ClientId = NetworkManager.LocalClientId, diff --git a/Runtime/Serialization/BitWriter.cs b/Runtime/Serialization/BitWriter.cs index 9eacd56..0e3ccfb 100644 --- a/Runtime/Serialization/BitWriter.cs +++ b/Runtime/Serialization/BitWriter.cs @@ -62,7 +62,7 @@ namespace Unity.Netcode /// When you know you will be writing multiple fields back-to-back and you know the total size, /// you can call TryBeginWriteBits() once on the total size, and then follow it with calls to /// WriteBit() or WriteBits(). - /// + /// /// Bitwise write operations will throw OverflowException in editor and development builds if you /// go past the point you've marked using TryBeginWriteBits(). In release builds, OverflowException will not be thrown /// for performance reasons, since the point of using TryBeginWrite is to avoid bounds checking in the following diff --git a/Runtime/Spawning/NetworkSpawnManager.cs b/Runtime/Spawning/NetworkSpawnManager.cs index c17e056..854bc8f 100644 --- a/Runtime/Spawning/NetworkSpawnManager.cs +++ b/Runtime/Spawning/NetworkSpawnManager.cs @@ -88,6 +88,13 @@ namespace Unity.Netcode } } + // Only if spawn with observers is set or we are using a distributed authority network topology and this is the client's player should we add + // the owner as an observer. + if (playerObject.SpawnWithObservers || (NetworkManager.DistributedAuthorityMode && NetworkManager.LocalClientId == playerObject.OwnerClientId)) + { + playerObject.Observers.Add(playerObject.OwnerClientId); + } + m_PlayerObjects.Add(playerObject); if (!m_PlayerObjectsTable.ContainsKey(playerObject.OwnerClientId)) { @@ -110,8 +117,9 @@ namespace Unity.Netcode if (playerNetworkClient.PlayerObject != null && m_PlayerObjects.Contains(playerNetworkClient.PlayerObject)) { // Just remove the previous player object but keep the assigned observers of the NetworkObject - RemovePlayerObject(playerNetworkClient.PlayerObject, true); + RemovePlayerObject(playerNetworkClient.PlayerObject); } + // Now update the associated NetworkClient's player object NetworkManager.ConnectionManager.ConnectedClients[playerObject.OwnerClientId].AssignPlayerObject(ref playerObject); AddPlayerObject(playerObject); @@ -120,7 +128,7 @@ namespace Unity.Netcode /// /// Removes a player object and updates all other players' observers list /// - private void RemovePlayerObject(NetworkObject playerObject, bool keepObservers = false) + private void RemovePlayerObject(NetworkObject playerObject, bool destroyingObject = false) { if (!playerObject.IsPlayerObject) { @@ -141,16 +149,21 @@ namespace Unity.Netcode } } - // If we want to keep the observers, then exit early - if (keepObservers) + if (NetworkManager.ConnectionManager.ConnectedClients.ContainsKey(playerObject.OwnerClientId) && destroyingObject) { - return; + NetworkManager.ConnectionManager.ConnectedClients[playerObject.OwnerClientId].PlayerObject = null; } - foreach (var player in m_PlayerObjects) - { - player.Observers.Remove(playerObject.OwnerClientId); - } + // If we want to keep the observers, then exit early + //if (keepObservers) + //{ + // return; + //} + + //foreach (var player in m_PlayerObjects) + //{ + // player.Observers.Remove(playerObject.OwnerClientId); + //} } internal void MarkObjectForShowingTo(NetworkObject networkObject, ulong clientId) @@ -409,27 +422,8 @@ namespace Unity.Netcode { if (NetworkManager.DistributedAuthorityMode && !NetworkManager.ShutdownInProgress) { - if (networkObject.IsOwnershipDistributable || networkObject.IsOwnershipTransferable) - { - if (networkObject.IsOwner || NetworkManager.DAHost) - { - NetworkLog.LogWarning("DANGO-TODO: Determine if removing ownership should make the CMB Service redistribute ownership or if this just isn't a valid thing in DAMode."); - return; - } - else - { - NetworkLog.LogError($"Only the owner is allowed to remove ownership in distributed authority mode!"); - return; - } - } - else - { - if (!NetworkManager.DAHost) - { - Debug.LogError($"Only {nameof(NetworkObject)}s with {nameof(NetworkObject.IsOwnershipDistributable)} or {nameof(NetworkObject.IsOwnershipTransferable)} set can perform ownership changes!"); - } - return; - } + Debug.LogError($"Removing ownership is invalid in Distributed Authority Mode. Use {nameof(ChangeOwnership)} instead."); + return; } ChangeOwnership(networkObject, NetworkManager.ServerClientId, true); } @@ -461,6 +455,18 @@ namespace Unity.Netcode if (NetworkManager.DistributedAuthorityMode) { + // Ensure only the session owner can change ownership (i.e. acquire) and that the session owner is not trying to assign a non-session owner client + // ownership of a NetworkObject with SessionOwner permissions. + if (networkObject.IsOwnershipSessionOwner && (!NetworkManager.LocalClient.IsSessionOwner || clientId != NetworkManager.CurrentSessionOwner)) + { + if (NetworkManager.LogLevel <= LogLevel.Developer) + { + NetworkLog.LogErrorServer($"[{networkObject.name}][Session Owner Only] You cannot change ownership of a {nameof(NetworkObject)} that has the {NetworkObject.OwnershipStatus.SessionOwner} flag set!"); + } + networkObject.OnOwnershipPermissionsFailure?.Invoke(NetworkObject.OwnershipPermissionsFailureStatus.SessionOwnerOnly); + return; + } + // If are not authorized and this is not an approved ownership change, then check to see if we can change ownership if (!isAuthorized && !isRequestApproval) { @@ -567,7 +573,6 @@ namespace Unity.Netcode { networkObject.ChildNetworkBehaviours[i].UpdateNetworkProperties(); } - size = NetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, NetworkManager.ServerClientId); NetworkManager.NetworkMetrics.TrackOwnershipChangeSent(NetworkManager.LocalClientId, networkObject, size); } @@ -724,12 +729,20 @@ namespace Unity.Netcode internal NetworkObject InstantiateAndSpawnNoParameterChecks(NetworkObject networkPrefab, ulong ownerClientId = NetworkManager.ServerClientId, bool destroyWithScene = false, bool isPlayerObject = false, bool forceOverride = false, Vector3 position = default, Quaternion rotation = default) { var networkObject = networkPrefab; - // Host spawns the ovveride and server spawns the original prefab unless forceOverride is set to true where both server or host will spawn the override. - // In distributed authority mode, we alaways get the override - if (forceOverride || NetworkManager.IsHost || NetworkManager.DistributedAuthorityMode) + // - Host and clients always instantiate the override if one exists. + // - Server instantiates the original prefab unless: + // -- forceOverride is set to true =or= + // -- The prefab has a registered prefab handler, then we let user code determine what to spawn. + // - Distributed authority mode always spawns the override if one exists. + if (forceOverride || NetworkManager.IsClient || NetworkManager.DistributedAuthorityMode || NetworkManager.PrefabHandler.ContainsHandler(networkPrefab.GlobalObjectIdHash)) { networkObject = GetNetworkObjectToSpawn(networkPrefab.GlobalObjectIdHash, ownerClientId, position, rotation); } + else // Under this case, server instantiate the prefab passed in. + { + networkObject = InstantiateNetworkPrefab(networkPrefab.gameObject, networkPrefab.GlobalObjectIdHash, position, rotation); + } + if (networkObject == null) { Debug.LogError($"Failed to instantiate and spawn {networkPrefab.name}!"); @@ -738,12 +751,20 @@ namespace Unity.Netcode networkObject.IsPlayerObject = isPlayerObject; networkObject.transform.position = position; networkObject.transform.rotation = rotation; - networkObject.SpawnWithOwnership(ownerClientId, destroyWithScene); + // If spawning as a player, then invoke SpawnAsPlayerObject + if (isPlayerObject) + { + networkObject.SpawnAsPlayerObject(ownerClientId, destroyWithScene); + } + else // Otherwise just spawn with ownership + { + networkObject.SpawnWithOwnership(ownerClientId, destroyWithScene); + } return networkObject; } /// - /// Gets the right NetworkObject prefab instance to spawn. If a handler is registered or there is an override assigned to the + /// Gets the right NetworkObject prefab instance to spawn. If a handler is registered or there is an override assigned to the /// passed in globalObjectIdHash value, then that is what will be instantiated, spawned, and returned. /// internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ownerId, Vector3? position, Quaternion? rotation, bool isScenePlaced = false) @@ -775,8 +796,8 @@ namespace Unity.Netcode case NetworkPrefabOverride.Hash: case NetworkPrefabOverride.Prefab: { - // When scene management is disabled and this is an in-scene placed NetworkObject, we want to always use the - // SourcePrefabToOverride and not any possible prefab override as a user might want to spawn overrides dynamically + // When scene management is disabled and this is an in-scene placed NetworkObject, we want to always use the + // SourcePrefabToOverride and not any possible prefab override as a user might want to spawn overrides dynamically // but might want to use the same source network prefab as an in-scene placed NetworkObject. // (When scene management is enabled, clients don't delete their in-scene placed NetworkObjects prior to dynamically // spawning them so the original prefab placed is preserved and this is not needed) @@ -804,16 +825,37 @@ namespace Unity.Netcode else { // Create prefab instance while applying any pre-assigned position and rotation values - networkObject = UnityEngine.Object.Instantiate(networkPrefabReference).GetComponent(); - networkObject.transform.position = position ?? networkObject.transform.position; - networkObject.transform.rotation = rotation ?? networkObject.transform.rotation; - networkObject.NetworkManagerOwner = NetworkManager; - networkObject.PrefabGlobalObjectIdHash = globalObjectIdHash; + networkObject = InstantiateNetworkPrefab(networkPrefabReference, globalObjectIdHash, position, rotation); } } return networkObject; } + /// + /// Instantiates a network prefab instance, assigns the base prefab , positions, and orients + /// the instance. + /// !!! Should only be invoked by unless used by an integration test !!! + /// + /// + /// should be the base prefab value and not the + /// overrided value. + /// (Can be used for integration testing) + /// + /// prefab to instantiate + /// of the base prefab instance + /// conditional position in place of the network prefab's default position + /// conditional rotation in place of the network prefab's default rotation + /// the instance of the + internal NetworkObject InstantiateNetworkPrefab(GameObject networkPrefab, uint prefabGlobalObjectIdHash, Vector3? position, Quaternion? rotation) + { + var networkObject = UnityEngine.Object.Instantiate(networkPrefab).GetComponent(); + networkObject.transform.position = position ?? networkObject.transform.position; + networkObject.transform.rotation = rotation ?? networkObject.transform.rotation; + networkObject.NetworkManagerOwner = NetworkManager; + networkObject.PrefabGlobalObjectIdHash = prefabGlobalObjectIdHash; + return networkObject; + } + /// /// Creates a local NetowrkObject to be spawned. /// @@ -949,7 +991,7 @@ namespace Unity.Netcode /// - NetworkObject when spawning a newly instantiated NetworkObject for the first time. /// - NetworkSceneManager after a server/session-owner has loaded a scene to locally spawn the newly instantiated in-scene placed NetworkObjects. /// - NetworkSpawnManager when spawning any already loaded in-scene placed NetworkObjects (client-server or session owner). - /// + /// /// Client-Server: /// Server is the only instance that invokes this method. /// @@ -1098,6 +1140,12 @@ namespace Unity.Netcode // then add all connected clients as observers if (!NetworkManager.DistributedAuthorityMode && NetworkManager.IsServer && networkObject.SpawnWithObservers) { + // If running as a server only, then make sure to always add the server's client identifier + if (!NetworkManager.IsHost) + { + networkObject.Observers.Add(NetworkManager.LocalClientId); + } + // Add client observers for (int i = 0; i < NetworkManager.ConnectedClientsIds.Count; i++) { @@ -1321,7 +1369,7 @@ namespace Unity.Netcode } } - // If spawned, then despawn and potentially destroy. + // If spawned, then despawn and potentially destroy. if (networkObjects[i].IsSpawned) { OnDespawnObject(networkObjects[i], shouldDestroy); @@ -1401,6 +1449,15 @@ namespace Unity.Netcode } } + // Since we are spawing in-scene placed NetworkObjects for already loaded scenes, + // we need to add any in-scene placed NetworkObject to our tracking table + var clearFirst = true; + foreach (var sceneLoaded in NetworkManager.SceneManager.ScenesLoaded) + { + NetworkManager.SceneManager.PopulateScenePlacedObjects(sceneLoaded.Value, clearFirst); + clearFirst = false; + } + // Notify all in-scene placed NetworkObjects have been spawned foreach (var networkObject in networkObjectsToSpawn) { @@ -1550,23 +1607,9 @@ namespace Unity.Netcode SpawnedObjectsList.Remove(networkObject); } - // DANGO-TODO: When we fix the issue with observers not being applied to NetworkObjects, - // (client connect/disconnect) we can remove this hacky way of doing this. - // Basically, when a player disconnects and/or is destroyed they are removed as an observer from all other client - // NetworkOject instances. - if (networkObject.IsPlayerObject && !networkObject.IsOwner && networkObject.OwnerClientId != NetworkManager.LocalClientId) - { - foreach (var netObject in SpawnedObjects) - { - if (netObject.Value.Observers.Contains(networkObject.OwnerClientId)) - { - netObject.Value.Observers.Remove(networkObject.OwnerClientId); - } - } - } if (networkObject.IsPlayerObject) { - RemovePlayerObject(networkObject); + RemovePlayerObject(networkObject, destroyGameObject); } // Always clear out the observers list when despawned @@ -1705,6 +1748,11 @@ namespace Unity.Netcode foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList) { + if (networkObject.IsOwnershipSessionOwner) + { + continue; + } + if (networkObject.IsOwnershipDistributable && !networkObject.IsOwnershipLocked) { if (networkObject.transform.parent != null) @@ -1715,17 +1763,15 @@ namespace Unity.Netcode continue; } } + // We have to check if it is an in-scene placed NetworkObject and if it is get the source prefab asset GlobalObjectIdHash value of the in-scene placed instance + // since all in-scene placed instances use unique GlobalObjectIdHash values. + var globalOjectIdHash = networkObject.IsSceneObject.HasValue && networkObject.IsSceneObject.Value ? networkObject.InScenePlacedSourceGlobalObjectIdHash : networkObject.GlobalObjectIdHash; - if (networkObject.IsSceneObject.Value) + if (!objectTypeCount.ContainsKey(globalOjectIdHash)) { - continue; + objectTypeCount.Add(globalOjectIdHash, 0); } - - if (!objectTypeCount.ContainsKey(networkObject.GlobalObjectIdHash)) - { - objectTypeCount.Add(networkObject.GlobalObjectIdHash, 0); - } - objectTypeCount[networkObject.GlobalObjectIdHash] += 1; + objectTypeCount[globalOjectIdHash] += 1; // DANGO-TODO-MVP: Remove this once the service handles object distribution if (onlyIncludeOwnedObjects && !networkObject.IsOwner) @@ -1733,133 +1779,141 @@ namespace Unity.Netcode continue; } + // Divide up by prefab type (GlobalObjectIdHash) to get a better distribution of object types - if (!objectByTypeAndOwner.ContainsKey(networkObject.GlobalObjectIdHash)) + if (!objectByTypeAndOwner.ContainsKey(globalOjectIdHash)) { - objectByTypeAndOwner.Add(networkObject.GlobalObjectIdHash, new Dictionary>()); + objectByTypeAndOwner.Add(globalOjectIdHash, new Dictionary>()); } // Sub-divide each type by owner - if (!objectByTypeAndOwner[networkObject.GlobalObjectIdHash].ContainsKey(networkObject.OwnerClientId)) + if (!objectByTypeAndOwner[globalOjectIdHash].ContainsKey(networkObject.OwnerClientId)) { - objectByTypeAndOwner[networkObject.GlobalObjectIdHash].Add(networkObject.OwnerClientId, new List()); + objectByTypeAndOwner[globalOjectIdHash].Add(networkObject.OwnerClientId, new List()); } // Add to the client's spawned object list - objectByTypeAndOwner[networkObject.GlobalObjectIdHash][networkObject.OwnerClientId].Add(networkObject); + objectByTypeAndOwner[globalOjectIdHash][networkObject.OwnerClientId].Add(networkObject); } } } internal void DistributeNetworkObjects(ulong clientId) { - // Distributed authority mode ownership distribution - // DANGO-TODO-MVP: Remove the session owner object distribution check once the service handles object distribution - if (NetworkManager.DistributedAuthorityMode && (NetworkManager.DAHost || NetworkManager.CMBServiceConnection)) + if (!NetworkManager.DistributedAuthorityMode) { - // DA-NGO CMB SERVICE NOTES: - // The most basic object distribution should be broken up into a table of spawned object types - // where each type contains a list of each client's owned objects of that type that can be - // distributed. - // The table format: - // [GlobalObjectIdHashValue][ClientId][List of Owned Objects] - var distributedNetworkObjects = new Dictionary>>(); + return; + } - // DA-NGO CMB SERVICE NOTES: - // This is optional, but I found it easier to get the total count of spawned objects for each prefab - // type contained in the previous table in order to be able to calculate the targeted object distribution - // count of that type per client. - var objectTypeCount = new Dictionary(); + if (NetworkManager.SessionConfig.ServiceSideDistribution) + { + return; + } - // Get all spawned objects by type and then by client owner that are spawned and can be distributed - GetObjectDistribution(ref distributedNetworkObjects, ref objectTypeCount); - var clientCount = NetworkManager.ConnectedClientsIds.Count; + // DA-NGO CMB SERVICE NOTES: + // The most basic object distribution should be broken up into a table of spawned object types + // where each type contains a list of each client's owned objects of that type that can be + // distributed. + // The table format: + // [GlobalObjectIdHashValue][ClientId][List of Owned Objects] + var distributedNetworkObjects = new Dictionary>>(); - // Cycle through each prefab type - foreach (var objectTypeEntry in distributedNetworkObjects) + // DA-NGO CMB SERVICE NOTES: + // This is optional, but I found it easier to get the total count of spawned objects for each prefab + // type contained in the previous table in order to be able to calculate the targeted object distribution + // count of that type per client. + var objectTypeCount = new Dictionary(); + + // Get all spawned objects by type and then by client owner that are spawned and can be distributed + GetObjectDistribution(ref distributedNetworkObjects, ref objectTypeCount); + + var clientCount = NetworkManager.ConnectedClientsIds.Count; + + // Cycle through each prefab type + foreach (var objectTypeEntry in distributedNetworkObjects) + { + // Calculate the number of objects that should be distributed amongst the clients + var totalObjectsToDistribute = objectTypeCount[objectTypeEntry.Key]; + var objPerClientF = totalObjectsToDistribute * (1.0f / clientCount); + var floorValue = (int)Math.Floor(objPerClientF); + var fractional = objPerClientF - floorValue; + var objPerClient = 0; + if (fractional >= 0.556f) { - // Calculate the number of objects that should be distributed amongst the clients - var totalObjectsToDistribute = objectTypeCount[objectTypeEntry.Key]; - var objPerClientF = totalObjectsToDistribute * (1.0f / clientCount); - var floorValue = (int)Math.Floor(objPerClientF); - var fractional = objPerClientF - floorValue; - var objPerClient = 0; - if (fractional >= 0.556f) - { - objPerClient = (int)Math.Round(totalObjectsToDistribute * (1.0f / clientCount)); - } - else - { - objPerClient = floorValue; - } + objPerClient = (int)Math.Round(totalObjectsToDistribute * (1.0f / clientCount)); + } + else + { + objPerClient = floorValue; + } - // If the object per client count is zero, then move to the next type. - if (objPerClient <= 0) + // If the object per client count is zero, then move to the next type. + if (objPerClient <= 0) + { + continue; + } + + // Evenly distribute this object type amongst the clients + foreach (var ownerList in objectTypeEntry.Value) + { + if (ownerList.Value.Count <= 1) { continue; } - // Evenly distribute this object type amongst the clients - foreach (var ownerList in objectTypeEntry.Value) + var maxDistributeCount = Mathf.Max(ownerList.Value.Count - objPerClient, 1); + var distributed = 0; + + // For now when we have more players then distributed NetworkObjects that + // a specific client owns, just assign half of the NetworkObjects to the new client + var offsetCount = Mathf.Max((int)Math.Round((float)(ownerList.Value.Count / objPerClient)), 1); + if (EnableDistributeLogging) { - if (ownerList.Value.Count <= 1) - { - continue; - } + Debug.Log($"[{objPerClient} of {totalObjectsToDistribute}][Client-{ownerList.Key}] Count: {ownerList.Value.Count} | ObjPerClient: {objPerClient} | maxD: {maxDistributeCount} | Offset: {offsetCount}"); + } - var maxDistributeCount = Mathf.Max(ownerList.Value.Count - objPerClient, 1); - var distributed = 0; - - // For now when we have more players then distributed NetworkObjects that - // a specific client owns, just assign half of the NetworkObjects to the new client - var offsetCount = Mathf.Max((int)Math.Round((float)(ownerList.Value.Count / objPerClient)), 1); - if (EnableDistributeLogging) + for (int i = 0; i < ownerList.Value.Count; i++) + { + if ((i % offsetCount) == 0) { - Debug.Log($"[{objPerClient} of {totalObjectsToDistribute}][Client-{ownerList.Key}] Count: {ownerList.Value.Count} | ObjPerClient: {objPerClient} | maxD: {maxDistributeCount} | Offset: {offsetCount}"); - } - - for (int i = 0; i < ownerList.Value.Count; i++) - { - if ((i % offsetCount) == 0) + ChangeOwnership(ownerList.Value[i], clientId, true); + //if (EnableDistributeLogging) { - ChangeOwnership(ownerList.Value[i], clientId, true); - if (EnableDistributeLogging) - { - Debug.Log($"[Client-{ownerList.Key}][NetworkObjectId-{ownerList.Value[i].NetworkObjectId} Distributed to Client-{clientId}"); - } - distributed++; - } - if (distributed == maxDistributeCount) - { - break; + Debug.Log($"[Client-{ownerList.Key}][NetworkObjectId-{ownerList.Value[i].NetworkObjectId} Distributed to Client-{clientId}"); } + distributed++; + } + if (distributed == maxDistributeCount) + { + break; } } } - - // If EnableDistributeLogging is enabled, log the object type distribution counts per client - if (EnableDistributeLogging) - { - var builder = new StringBuilder(); - distributedNetworkObjects.Clear(); - objectTypeCount.Clear(); - GetObjectDistribution(ref distributedNetworkObjects, ref objectTypeCount); - builder.AppendLine($"Client Relative Distributed Object Count: (distribution follows)"); - // Cycle through each prefab type - foreach (var objectTypeEntry in distributedNetworkObjects) - { - builder.AppendLine($"[GID: {objectTypeEntry.Key} | {objectTypeEntry.Value.First().Value.First().name}][Total Count: {objectTypeCount[objectTypeEntry.Key]}]"); - builder.AppendLine($"[GID: {objectTypeEntry.Key} | {objectTypeEntry.Value.First().Value.First().name}] Distribution:"); - // Evenly distribute this type amongst clients - foreach (var ownerList in objectTypeEntry.Value) - { - builder.AppendLine($"[Client-{ownerList.Key}] Count: {ownerList.Value.Count}"); - } - } - Debug.Log(builder.ToString()); - } } + + // If EnableDistributeLogging is enabled, log the object type distribution counts per client + if (EnableDistributeLogging) + { + var builder = new StringBuilder(); + distributedNetworkObjects.Clear(); + objectTypeCount.Clear(); + GetObjectDistribution(ref distributedNetworkObjects, ref objectTypeCount); + builder.AppendLine($"Client Relative Distributed Object Count: (distribution follows)"); + // Cycle through each prefab type + foreach (var objectTypeEntry in distributedNetworkObjects) + { + builder.AppendLine($"[GID: {objectTypeEntry.Key} | {objectTypeEntry.Value.First().Value.First().name}][Total Count: {objectTypeCount[objectTypeEntry.Key]}]"); + builder.AppendLine($"[GID: {objectTypeEntry.Key} | {objectTypeEntry.Value.First().Value.First().name}] Distribution:"); + // Evenly distribute this type amongst clients + foreach (var ownerList in objectTypeEntry.Value) + { + builder.AppendLine($"[Client-{ownerList.Key}] Count: {ownerList.Value.Count}"); + } + } + Debug.Log(builder.ToString()); + } + } internal struct DeferredDespawnObject @@ -1969,14 +2023,14 @@ namespace Unity.Netcode /// synchronizing in order to "show" (spawn) anything that might be currently hidden from /// the session owner. /// + /// + /// Replacement is: SynchronizeObjectsToNewlyJoinedClient + /// internal void ShowHiddenObjectsToNewlyJoinedClient(ulong newClientId) { - if (!NetworkManager.DistributedAuthorityMode) + if (NetworkManager == null || NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer) { - if (NetworkManager == null || !NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer) - { - Debug.LogWarning($"[Internal Error] {nameof(ShowHiddenObjectsToNewlyJoinedClient)} invoked while !"); - } + Debug.LogWarning($"[Internal Error] {nameof(ShowHiddenObjectsToNewlyJoinedClient)} invoked while shutdown is in progress!"); return; } @@ -2012,5 +2066,46 @@ namespace Unity.Netcode } } } + + internal void SynchronizeObjectsToNewlyJoinedClient(ulong newClientId) + { + if (NetworkManager == null || NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer) + { + Debug.LogWarning($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} invoked while shutdown is in progress!"); + return; + } + + if (!NetworkManager.DistributedAuthorityMode) + { + Debug.LogError($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} should only be invoked when using a distributed authority network topology!"); + return; + } + + if (NetworkManager.NetworkConfig.EnableSceneManagement) + { + Debug.LogError($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} should only be invoked when scene management is disabled!"); + return; + } + + var localClientId = NetworkManager.LocalClient.ClientId; + foreach (var networkObject in SpawnedObjectsList) + { + if (networkObject.SpawnWithObservers && networkObject.OwnerClientId == localClientId) + { + if (networkObject.Observers.Contains(newClientId)) + { + if (NetworkManager.LogLevel <= LogLevel.Developer) + { + // Temporary tracking to make sure we are not showing something already visibile (should never be the case for this) + Debug.LogWarning($"[{nameof(SynchronizeObjectsToNewlyJoinedClient)}][{networkObject.name}] New client as already an observer!"); + } + // For now, remove the client (impossible for the new client to have an instance since the session owner doesn't) to make sure newly added + // code to handle this edge case works. + networkObject.Observers.Remove(newClientId); + } + networkObject.NetworkShow(newClientId); + } + } + } } } diff --git a/Runtime/Transports/NetworkTransport.cs b/Runtime/Transports/NetworkTransport.cs index b624120..d647aea 100644 --- a/Runtime/Transports/NetworkTransport.cs +++ b/Runtime/Transports/NetworkTransport.cs @@ -107,6 +107,45 @@ namespace Unity.Netcode /// /// optionally pass in NetworkManager public abstract void Initialize(NetworkManager networkManager = null); + /// + /// Invoked by NetworkManager at the beginning of its EarlyUpdate. + /// For order of operations see: + /// + /// Useful to handle processing any transport-layer events such as processing inbound messages or changes in connection state(s). + ///
+ protected virtual void OnEarlyUpdate() + { + + } + + /// + /// Invoked by NetworkManager at the beginning of its EarlyUpdate + /// + internal void EarlyUpdate() + { + OnEarlyUpdate(); + } + + /// + /// Invoked by NetworkManager towards the end of the PostLateUpdate. + /// For order of operations see: + /// + /// + /// Useful to handle any end of frame transport tasks such as sending queued transport messages. + /// + protected virtual void OnPostLateUpdate() + { + + } + + /// + /// Invoked by NetworkManager towards the end of the PostLateUpdate + /// + internal void PostLateUpdate() + { + OnPostLateUpdate(); + } + protected virtual NetworkTopologyTypes OnCurrentTopology() { return NetworkTopologyTypes.ClientServer; diff --git a/Runtime/Transports/UTP/UnityTransport.cs b/Runtime/Transports/UTP/UnityTransport.cs index 0237517..634d544 100644 --- a/Runtime/Transports/UTP/UnityTransport.cs +++ b/Runtime/Transports/UTP/UnityTransport.cs @@ -405,6 +405,7 @@ namespace Unity.Netcode.Transports.UTP #if UTP_TRANSPORT_2_0_ABOVE [Obsolete("DebugSimulator is no longer supported and has no effect. Use Network Simulator from the Multiplayer Tools package.", false)] + [HideInInspector] #endif public SimulatorParameters DebugSimulator = new SimulatorParameters { @@ -944,17 +945,13 @@ namespace Unity.Netcode.Transports.UTP return false; } - private void Update() + /// + /// Handles accepting new connections and processing transport events. + /// + protected override void OnEarlyUpdate() { if (m_Driver.IsCreated) { - foreach (var kvp in m_SendQueue) - { - SendBatchedMessages(kvp.Key, kvp.Value); - } - - m_Driver.ScheduleUpdate().Complete(); - if (m_ProtocolType == ProtocolType.RelayUnityTransport && m_Driver.GetRelayConnectionStatus() == RelayConnectionStatus.AllocationInvalid) { Debug.LogError("Transport failure! Relay allocation needs to be recreated, and NetworkManager restarted. " + @@ -964,15 +961,38 @@ namespace Unity.Netcode.Transports.UTP return; } + m_Driver.ScheduleUpdate().Complete(); + + // Process any new connections while (AcceptConnection() && m_Driver.IsCreated) { ; } + // Process any transport events (i.e. connect, disconnect, data, etc) while (ProcessEvent() && m_Driver.IsCreated) { ; } + } + base.OnEarlyUpdate(); + } + + /// + /// Handles sending any queued batched messages. + /// + protected override void OnPostLateUpdate() + { + if (m_Driver.IsCreated) + { + foreach (var kvp in m_SendQueue) + { + SendBatchedMessages(kvp.Key, kvp.Value); + } + + // Schedule a flush send as the last transport action for the + // current frame. + m_Driver.ScheduleFlushSend(default).Complete(); #if MULTIPLAYER_TOOLS_1_0_0_PRE_7 if (m_NetworkManager) @@ -981,6 +1001,7 @@ namespace Unity.Netcode.Transports.UTP } #endif } + base.OnPostLateUpdate(); } private void OnDestroy() @@ -1241,6 +1262,30 @@ namespace Unity.Netcode.Transports.UTP return (ulong)ExtractRtt(ParseClientId(clientId)); } + /// + /// Provides the for the NGO client identifier specified. + /// + /// + /// - This is only really useful for direct connections. + /// - Relay connections and clients connected using a distributed authority network topology will not provide the client's actual endpoint information. + /// - For LAN topologies this should work as long as it is a direct connection and not a relay connection. + /// + /// NGO client identifier to get endpoint information about. + /// + public NetworkEndpoint GetEndpoint(ulong clientId) + { + if (m_Driver.IsCreated && m_NetworkManager != null && m_NetworkManager.IsListening) + { + var transportId = m_NetworkManager.ConnectionManager.ClientIdToTransportId(clientId); + var networkConnection = ParseClientId(transportId); + if (m_Driver.GetConnectionState(networkConnection) == NetworkConnection.State.Connected) + { + return m_Driver.GetRemoteEndpoint(networkConnection); + } + } + return new NetworkEndpoint(); + } + /// /// Initializes the transport /// @@ -1450,8 +1495,18 @@ namespace Unity.Netcode.Transports.UTP /// public override void Shutdown() { + if (m_NetworkManager && !m_NetworkManager.ShutdownInProgress) + { + Debug.LogWarning("Directly calling `UnityTransport.Shutdown()` results in unexpected shutdown behaviour. All pending events will be lost. Use `NetworkManager.Shutdown()` instead."); + } + if (m_Driver.IsCreated) { + while (ProcessEvent() && m_Driver.IsCreated) + { + ; + } + // Flush all send queues to the network. NGO can be configured to flush its message // queue on shutdown. But this only calls the Send() method, which doesn't actually // get anything to the network. @@ -1469,6 +1524,7 @@ namespace Unity.Netcode.Transports.UTP DisposeInternals(); m_ReliableReceiveQueues.Clear(); + m_State = State.Disconnected; // We must reset this to zero because UTP actually re-uses clientIds if there is a clean disconnect m_ServerClientId = 0; diff --git a/Runtime/com.unity.netcode.runtime.asmdef b/Runtime/com.unity.netcode.runtime.asmdef index f1ff7ec..1f02e57 100644 --- a/Runtime/com.unity.netcode.runtime.asmdef +++ b/Runtime/com.unity.netcode.runtime.asmdef @@ -58,16 +58,6 @@ "expression": "", "define": "COM_UNITY_MODULES_ANIMATION" }, - { - "name": "com.unity.modules.physics", - "expression": "", - "define": "COM_UNITY_MODULES_PHYSICS" - }, - { - "name": "com.unity.modules.physics2d", - "expression": "", - "define": "COM_UNITY_MODULES_PHYSICS2D" - }, { "name": "com.unity.services.multiplayer", "expression": "0.2.0", diff --git a/Samples~/Bootstrap/.sample.json b/Samples~/Bootstrap/.sample.json deleted file mode 100644 index f62cf30..0000000 --- a/Samples~/Bootstrap/.sample.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "displayName": "Bootstrap", - "description": "A lightweight sample to get started" -} \ No newline at end of file diff --git a/Samples~/Bootstrap/Scripts/Bootstrap.asmdef b/Samples~/Bootstrap/Scripts/Bootstrap.asmdef index 07a8ac0..54cb675 100644 --- a/Samples~/Bootstrap/Scripts/Bootstrap.asmdef +++ b/Samples~/Bootstrap/Scripts/Bootstrap.asmdef @@ -1,7 +1,7 @@ { - "name": "Bootstrap", + "name": "Bootstrap", "rootNamespace": "Unity.Netcode.Samples", "references": [ "Unity.Netcode.Runtime" ] -} +} \ No newline at end of file diff --git a/TestHelpers/Runtime/IntegrationTestWithApproximation.cs b/TestHelpers/Runtime/IntegrationTestWithApproximation.cs index 02a5393..89b1e89 100644 --- a/TestHelpers/Runtime/IntegrationTestWithApproximation.cs +++ b/TestHelpers/Runtime/IntegrationTestWithApproximation.cs @@ -87,6 +87,8 @@ namespace Unity.Netcode.TestHelpers.Runtime return new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max)); } + public IntegrationTestWithApproximation(NetworkTopologyTypes networkTopologyType, HostOrServer hostOrServer) : base(networkTopologyType, hostOrServer) { } + public IntegrationTestWithApproximation(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } public IntegrationTestWithApproximation(HostOrServer hostOrServer) : base(hostOrServer) { } diff --git a/TestHelpers/Runtime/NetcodeIntegrationTest.cs b/TestHelpers/Runtime/NetcodeIntegrationTest.cs index a84a7cc..921d70b 100644 --- a/TestHelpers/Runtime/NetcodeIntegrationTest.cs +++ b/TestHelpers/Runtime/NetcodeIntegrationTest.cs @@ -1759,6 +1759,13 @@ namespace Unity.Netcode.TestHelpers.Runtime m_DistributedAuthority = m_NetworkTopologyType == NetworkTopologyTypes.DistributedAuthority; } + public NetcodeIntegrationTest(NetworkTopologyTypes networkTopologyType, HostOrServer hostOrServer) + { + m_NetworkTopologyType = networkTopologyType; + m_DistributedAuthority = m_NetworkTopologyType == NetworkTopologyTypes.DistributedAuthority; + m_UseHost = hostOrServer == HostOrServer.Host || hostOrServer == HostOrServer.DAHost; + } + /// /// Optional Host or Server integration tests /// Constructor that allows you To break tests up as a host diff --git a/TestHelpers/Runtime/NetcodeIntegrationTestHelpers.cs b/TestHelpers/Runtime/NetcodeIntegrationTestHelpers.cs index 8758db8..1b4e094 100644 --- a/TestHelpers/Runtime/NetcodeIntegrationTestHelpers.cs +++ b/TestHelpers/Runtime/NetcodeIntegrationTestHelpers.cs @@ -559,6 +559,29 @@ namespace Unity.Netcode.TestHelpers.Runtime } } + /// + /// Creates a to be used with integration testing + /// + /// namr of the object + /// owner of the object + /// when true, the instance is automatically migrated into the DDOL + /// + internal static GameObject CreateNetworkObject(string baseName, NetworkManager owner, bool moveToDDOL = false) + { + var gameObject = new GameObject + { + name = baseName + }; + var networkObject = gameObject.AddComponent(); + networkObject.NetworkManagerOwner = owner; + MakeNetworkObjectTestPrefab(networkObject); + if (moveToDDOL) + { + Object.DontDestroyOnLoad(gameObject); + } + return gameObject; + } + public static GameObject CreateNetworkObjectPrefab(string baseName, NetworkManager server, params NetworkManager[] clients) { void AddNetworkPrefab(NetworkConfig config, NetworkPrefab prefab) @@ -570,13 +593,7 @@ namespace Unity.Netcode.TestHelpers.Runtime Assert.IsNotNull(server, prefabCreateAssertError); Assert.IsFalse(server.IsListening, prefabCreateAssertError); - var gameObject = new GameObject - { - name = baseName - }; - var networkObject = gameObject.AddComponent(); - networkObject.NetworkManagerOwner = server; - MakeNetworkObjectTestPrefab(networkObject); + var gameObject = CreateNetworkObject(baseName, server); var networkPrefab = new NetworkPrefab() { Prefab = gameObject }; // We could refactor this test framework to share a NetworkPrefabList instance, but at this point it's diff --git a/Tests.meta b/Tests.meta deleted file mode 100644 index 5be7b0d..0000000 --- a/Tests.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e5a2c06211b0c224c94202c2cda733fd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor.meta b/Tests/Editor.meta deleted file mode 100644 index ce7ba7d..0000000 --- a/Tests/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d656bc8bb2502584ab6883d254d64782 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/ArithmeticTests.cs b/Tests/Editor/ArithmeticTests.cs deleted file mode 100644 index 2791e4a..0000000 --- a/Tests/Editor/ArithmeticTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class ArithmeticTests - { - [Test] - public void TestCeil() - { - Assert.That(Arithmetic.CeilingExact(10, 5), Is.EqualTo(2)); - Assert.That(Arithmetic.CeilingExact(11, 5), Is.EqualTo(3)); - Assert.That(Arithmetic.CeilingExact(0, 5), Is.EqualTo(0)); - Assert.That(Arithmetic.CeilingExact(1, 5), Is.EqualTo(1)); - Assert.That(Arithmetic.CeilingExact(2, 5), Is.EqualTo(1)); - Assert.That(Arithmetic.CeilingExact(3, 5), Is.EqualTo(1)); - Assert.That(Arithmetic.CeilingExact(4, 5), Is.EqualTo(1)); - Assert.That(Arithmetic.CeilingExact(5, 5), Is.EqualTo(1)); - Assert.That(Arithmetic.CeilingExact(6, 5), Is.EqualTo(2)); - } - - [Test] - public void TestZigZag() - { - Assert.That(Arithmetic.ZigZagDecode(Arithmetic.ZigZagEncode(1234)), Is.EqualTo(1234)); - Assert.That(Arithmetic.ZigZagDecode(Arithmetic.ZigZagEncode(-1)), Is.EqualTo(-1)); - Assert.That(Arithmetic.ZigZagDecode(Arithmetic.ZigZagEncode(0)), Is.EqualTo(0)); - Assert.That(Arithmetic.ZigZagDecode(Arithmetic.ZigZagEncode(long.MaxValue)), Is.EqualTo(long.MaxValue)); - Assert.That(Arithmetic.ZigZagDecode(Arithmetic.ZigZagEncode(long.MinValue)), Is.EqualTo(long.MinValue)); - } - } -} diff --git a/Tests/Editor/ArithmeticTests.cs.meta b/Tests/Editor/ArithmeticTests.cs.meta deleted file mode 100644 index d169f79..0000000 --- a/Tests/Editor/ArithmeticTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cc0dc1cbf78a5486db1ccbc245d90992 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Build.meta b/Tests/Editor/Build.meta deleted file mode 100644 index ecc75f3..0000000 --- a/Tests/Editor/Build.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2a46bbc7e63044f498612ed996afa274 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Build/BuildTestScene.unity b/Tests/Editor/Build/BuildTestScene.unity deleted file mode 100644 index efc0871..0000000 --- a/Tests/Editor/Build/BuildTestScene.unity +++ /dev/null @@ -1,371 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657874, g: 0.49641275, b: 0.5748172, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &1290761662 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1290761665} - - component: {fileID: 1290761664} - - component: {fileID: 1290761663} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &1290761663 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1290761662} - m_Enabled: 1 ---- !u!20 &1290761664 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1290761662} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1290761665 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1290761662} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1858588911 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1858588913} - - component: {fileID: 1858588912} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1858588912 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1858588911} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &1858588913 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1858588911} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &1896907459 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1896907460} - - component: {fileID: 1896907461} - m_Layer: 0 - m_Name: '[NetworkManager]' - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1896907460 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1896907459} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1896907461 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1896907459} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} - m_Name: - m_EditorClassIdentifier: - DontDestroy: 1 - RunInBackground: 1 - LogLevel: 1 - NetworkConfig: - ProtocolVersion: 0 - NetworkTransport: {fileID: 0} - RegisteredScenes: - - BuildTestScene - AllowRuntimeSceneChanges: 0 - PlayerPrefab: {fileID: 0} - NetworkPrefabs: [] - TickRate: 30 - ClientConnectionBufferTimeout: 10 - ConnectionApproval: 0 - ConnectionData: - EnableTimeResync: 0 - TimeResyncInterval: 30 - EnableNetworkVariable: 1 - EnsureNetworkVariableLengthSafety: 0 - EnableSceneManagement: 1 - ForceSamePrefabs: 1 - RecycleNetworkIds: 1 - NetworkIdRecycleDelay: 120 - RpcHashSize: 0 - LoadSceneTimeOut: 120 - SpawnTimeout: 20 - EnableNetworkLogs: 1 diff --git a/Tests/Editor/Build/BuildTestScene.unity.meta b/Tests/Editor/Build/BuildTestScene.unity.meta deleted file mode 100644 index 0a8a789..0000000 --- a/Tests/Editor/Build/BuildTestScene.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d45c09a54b1da466ab6c385ee45fd3e4 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Build/BuildTests.cs b/Tests/Editor/Build/BuildTests.cs deleted file mode 100644 index 563c43b..0000000 --- a/Tests/Editor/Build/BuildTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -#if !MULTIPLAYER_TOOLS -using System.IO; -using System.Reflection; -using NUnit.Framework; -using UnityEditor; -using UnityEditor.Build.Reporting; -using UnityEngine; - -namespace Unity.Netcode.EditorTests -{ - internal class BuildTests - { - public const string DefaultBuildScenePath = "Tests/Editor/Build/BuildTestScene.unity"; - - [Test] - public void BasicBuildTest() - { - var execAssembly = Assembly.GetExecutingAssembly(); - var packagePath = UnityEditor.PackageManager.PackageInfo.FindForAssembly(execAssembly).assetPath; - var buildTarget = EditorUserBuildSettings.activeBuildTarget; - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget); - var buildTargetSupported = BuildPipeline.IsBuildTargetSupported(buildTargetGroup, buildTarget); - - if (buildTargetSupported) - { - var buildReport = BuildPipeline.BuildPlayer( - new[] { Path.Combine(packagePath, DefaultBuildScenePath) }, - Path.Combine(Path.GetDirectoryName(Application.dataPath), "Builds", nameof(BuildTests)), - buildTarget, - BuildOptions.None - ); - - Assert.AreEqual(BuildResult.Succeeded, buildReport.summary.result); - } - else - { - Debug.Log($"Skipped building player due to Unsupported Build Target"); - } - } - } -} -#endif diff --git a/Tests/Editor/Build/BuildTests.cs.meta b/Tests/Editor/Build/BuildTests.cs.meta deleted file mode 100644 index 705e96c..0000000 --- a/Tests/Editor/Build/BuildTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: efb549c2173d5478e93a71fbd05c0392 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/DisconnectMessageTests.cs b/Tests/Editor/DisconnectMessageTests.cs deleted file mode 100644 index e30cecc..0000000 --- a/Tests/Editor/DisconnectMessageTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using NUnit.Framework; -using Unity.Collections; - -namespace Unity.Netcode.EditorTests -{ - internal class DisconnectMessageTests - { - [Test] - public void EmptyDisconnectReason() - { - var networkContext = new NetworkContext(); - var writer = new FastBufferWriter(20, Allocator.Temp, 20); - var msg = new DisconnectReasonMessage - { - Reason = string.Empty - }; - msg.Serialize(writer, msg.Version); - - var fbr = new FastBufferReader(writer, Allocator.Temp); - var recvMsg = new DisconnectReasonMessage(); - recvMsg.Deserialize(fbr, ref networkContext, msg.Version); - - Assert.IsEmpty(recvMsg.Reason); - } - - [Test] - public void DisconnectReason() - { - var networkContext = new NetworkContext(); - var writer = new FastBufferWriter(20, Allocator.Temp, 20); - var msg = new DisconnectReasonMessage - { - Reason = "Foo" - }; - msg.Serialize(writer, msg.Version); - - var fbr = new FastBufferReader(writer, Allocator.Temp); - var recvMsg = new DisconnectReasonMessage(); - recvMsg.Deserialize(fbr, ref networkContext, msg.Version); - - Assert.AreEqual("Foo", recvMsg.Reason); - } - - [Test] - public void DisconnectReasonTooLong() - { - var networkContext = new NetworkContext(); - var writer = new FastBufferWriter(20, Allocator.Temp, 20); - var msg = new DisconnectReasonMessage - { - Reason = "ThisStringIsWayLongerThanTwentyBytes" - }; - msg.Serialize(writer, msg.Version); - - var fbr = new FastBufferReader(writer, Allocator.Temp); - var recvMsg = new DisconnectReasonMessage(); - recvMsg.Deserialize(fbr, ref networkContext, msg.Version); - - Assert.IsEmpty(recvMsg.Reason); - } - } -} diff --git a/Tests/Editor/DisconnectMessageTests.cs.meta b/Tests/Editor/DisconnectMessageTests.cs.meta deleted file mode 100644 index 8cfb8e2..0000000 --- a/Tests/Editor/DisconnectMessageTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 55a1355c62fe14a118253f8bbee7c3cf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/InterpolatorTests.cs b/Tests/Editor/InterpolatorTests.cs deleted file mode 100644 index 4cdd069..0000000 --- a/Tests/Editor/InterpolatorTests.cs +++ /dev/null @@ -1,361 +0,0 @@ -using System; -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class InterpolatorTests - { - private const float k_Precision = 0.00000001f; - private const int k_MockTickRate = 1; - - private NetworkTime T(float time, uint tickRate = k_MockTickRate) - { - return new NetworkTime(tickRate, timeSec: time); - } - - [Test] - public void TestReset() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - var serverTime = new NetworkTime(k_MockTickRate, 100f); - interpolator.AddMeasurement(5, 1.0f); - var initVal = interpolator.Update(10f, serverTime.Time, serverTime.TimeTicksAgo(1).Time); // big value - Assert.That(initVal, Is.EqualTo(5f)); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(5f)); - - interpolator.ResetTo(100f, serverTime.Time); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(100f)); - var val = interpolator.Update(1f, serverTime.Time, serverTime.TimeTicksAgo(1).Time); - Assert.That(val, Is.EqualTo(100f)); - } - - [Test] - public void NormalUsage() - { - // Testing float instead of Vector3. The only difference with Vector3 is the lerp method used. - var interpolator = new BufferedLinearInterpolatorFloat(); - - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0f)); - - interpolator.AddMeasurement(0f, 1.0f); - interpolator.AddMeasurement(1f, 2.0f); - - // too small update, nothing happens, doesn't consume from buffer yet - var serverTime = new NetworkTime(k_MockTickRate, 0.01d); // t = 0.1d - interpolator.Update(.01f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0f)); - - // consume first measurement, still can't interpolate with just one tick consumed - serverTime += 1.0d; // t = 1.01 - interpolator.Update(1.0f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0f)); - - // consume second measurement, start to interpolate - serverTime += 1.0d; // t = 2.01 - var valueFromUpdate = interpolator.Update(1.0f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0.01f).Within(k_Precision)); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0.01f).Within(k_Precision)); // test a second time, to make sure the get doesn't update the value - Assert.That(valueFromUpdate, Is.EqualTo(interpolator.GetInterpolatedValue()).Within(k_Precision)); - - // continue interpolation - serverTime = new NetworkTime(k_MockTickRate, 2.5d); // t = 2.5d - interpolator.Update(2.5f - 2.01f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0.5f).Within(k_Precision)); - - // check when reaching end - serverTime += 0.5d; // t = 3 - interpolator.Update(0.5f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1f).Within(k_Precision)); - } - - /// - /// Out of order or 'ACB' problem - /// Given two measurements have already arrived A and C, if a new measurement B arrives, the interpolation shouldn't go to B, but continue - /// to C. - /// Adding B should be ignored if interpolation is already interpolating between A and C - /// - [Test] - public void OutOfOrderShouldStillWork() - { - var serverTime = new NetworkTime(k_MockTickRate, 0.01d); - var interpolator = new BufferedLinearInterpolatorFloat(); - double timeStep = 0.5d; - - interpolator.AddMeasurement(0f, 0d); - interpolator.AddMeasurement(2f, 2d); - - serverTime = new NetworkTime(k_MockTickRate, 1.5d); - interpolator.Update(1.5f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(0f).Within(k_Precision)); - - serverTime += timeStep; // t = 2.0 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1f).Within(k_Precision)); - - serverTime += timeStep; // t = 2.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1.5f).Within(k_Precision)); - - // makes sure that interpolation still continues in right direction - interpolator.AddMeasurement(1, 1d); - - serverTime += timeStep; // t = 3 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(2f).Within(k_Precision)); - } - - [Ignore("TODO: Fix this test to still handle testing message loss without extrapolation")] - [Test] - public void MessageLoss() - { - var serverTime = new NetworkTime(k_MockTickRate, 0.01d); - var interpolator = new BufferedLinearInterpolatorFloat(); - double timeStep = 0.5d; - - interpolator.AddMeasurement(1f, 1d); - interpolator.AddMeasurement(2f, 2d); - // message time=3 was lost - interpolator.AddMeasurement(4f, 4d); - interpolator.AddMeasurement(5f, 5d); - // message time=6 was lost - interpolator.AddMeasurement(100f, 7d); // high value to produce a misprediction - - // first value teleports interpolator - serverTime = new NetworkTime(k_MockTickRate, 1d); - interpolator.Update(1f, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1f)); - - // nothing happens, not ready to consume second value yet - serverTime += timeStep; // t = 1.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1f)); - - // beginning of interpolation, second value consumed, currently at start - serverTime += timeStep; // t = 2 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1f)); - - // interpolation starts - serverTime += timeStep; // t = 2.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(1.5f)); - - serverTime += timeStep; // t = 3 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(2f)); - - // extrapolating to 2.5 - serverTime += timeStep; // t = 3.5d - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(2.5f)); - - // next value skips to where it was supposed to be once buffer time is showing the next value - serverTime += timeStep; // t = 4 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(3f)); - - // interpolation continues as expected - serverTime += timeStep; // t = 4.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(3.5f)); - - serverTime += timeStep; // t = 5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(4f)); - - // lost time=6, extrapolating - serverTime += timeStep; // t = 5.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(4.5f)); - - serverTime += timeStep; // t = 6.0 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(5f)); - - // misprediction - serverTime += timeStep; // t = 6.5 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.EqualTo(5.5f)); - - // lerp to right value - serverTime += timeStep; // t = 7.0 - interpolator.Update((float)timeStep, serverTime); - Assert.That(interpolator.GetInterpolatedValue(), Is.GreaterThan(6.0f)); - Assert.That(interpolator.GetInterpolatedValue(), Is.LessThanOrEqualTo(100f)); - } - - [Test] - public void AddFirstMeasurement() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - var serverTime = new NetworkTime(k_MockTickRate, 0d); - interpolator.AddMeasurement(2f, 1d); - interpolator.AddMeasurement(3f, 2d); - - serverTime += 1d; // t = 1 - var interpolatedValue = interpolator.Update(1f, serverTime); - // when consuming only one measurement and it's the first one consumed, teleport to it - Assert.That(interpolatedValue, Is.EqualTo(2f)); - - // then interpolation should work as usual - serverTime += 1d; // t = 2 - interpolatedValue = interpolator.Update(1f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(2f)); - - serverTime += 0.5d; // t = 2.5 - interpolatedValue = interpolator.Update(0.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(2.5f)); - - serverTime += 0.5d; // t = 3 - interpolatedValue = interpolator.Update(.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(3f)); - } - - [Test] - public void JumpToEachValueIfDeltaTimeTooBig() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - var serverTime = new NetworkTime(k_MockTickRate, 0d); - interpolator.AddMeasurement(2f, 1d); - interpolator.AddMeasurement(3f, 2d); - - serverTime += 1d; // t = 1 - var interpolatedValue = interpolator.Update(1f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(2f)); - - // big deltaTime, jumping to latest value - serverTime += 9f; // t = 10 - interpolatedValue = interpolator.Update(8f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(3)); - } - - [Test] - public void JumpToLastValueFromStart() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - var serverTime = new NetworkTime(k_MockTickRate, 0d); - - serverTime += 1d; // t = 1 - interpolator.AddMeasurement(1f, serverTime.Time); - serverTime += 1d; // t = 2 - interpolator.AddMeasurement(2f, serverTime.Time); - serverTime += 1d; // t = 3 - interpolator.AddMeasurement(3f, serverTime.Time); - - // big time jump - serverTime += 7d; // t = 10 - var interpolatedValue = interpolator.Update(10f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(3f)); - - // interpolation continues as normal - serverTime = new NetworkTime(k_MockTickRate, 11d); // t = 11 - interpolator.AddMeasurement(11f, serverTime.Time); // out of order - - serverTime = new NetworkTime(k_MockTickRate, 10.5d); // t = 10.5 - interpolatedValue = interpolator.Update(0.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(3f)); - - serverTime += 0.5d; // t = 11 - interpolatedValue = interpolator.Update(0.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(10f)); - - serverTime += 0.5d; // t = 11.5 - interpolatedValue = interpolator.Update(0.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(10.5f)); - - serverTime += 0.5d; // t = 12 - interpolatedValue = interpolator.Update(0.5f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(11f)); - } - - [Test] - public void TestBufferSizeLimit() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - // set first value - var serverTime = new NetworkTime(k_MockTickRate, 0d); - serverTime += 1.0d; // t = 1 - interpolator.AddMeasurement(-1f, serverTime.Time); - interpolator.Update(1f, serverTime); - - // max + 1 - serverTime += 1.0d; // t = 2 - interpolator.AddMeasurement(2, serverTime.Time); // +1, this should trigger a burst and teleport to last value - for (int i = 0; i < 100; i++) - { - interpolator.AddMeasurement(i + 3, i + 3d); - } - - // client was paused for a while, some time has past, we just got a burst of values from the server that teleported us to the last value received - serverTime = new NetworkTime(k_MockTickRate, 102d); - var interpolatedValue = interpolator.Update(101f, serverTime); - Assert.That(interpolatedValue, Is.EqualTo(102)); - } - - [Test] - public void TestUpdatingInterpolatorWithNoData() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - var serverTime = new NetworkTime(k_MockTickRate, 0.0d); - // invalid case, this is undefined behaviour - Assert.Throws(() => interpolator.Update(1f, serverTime)); - } - - [Ignore("TODO: Fix this test to still test duplicated values without extrapolation")] - [Test] - public void TestDuplicatedValues() - { - var interpolator = new BufferedLinearInterpolatorFloat(); - - var serverTime = new NetworkTime(k_MockTickRate, 0.0d); - - serverTime += 1d; // t = 1 - interpolator.AddMeasurement(1f, serverTime.Time); - serverTime += 1d; // t = 2 - interpolator.AddMeasurement(2f, serverTime.Time); - interpolator.AddMeasurement(2f, serverTime.Time); - - // empty interpolator teleports to initial value - serverTime = new NetworkTime(k_MockTickRate, 0.0d); - serverTime += 1d; // t = 1 - var interp = interpolator.Update(1f, serverTime); - Assert.That(interp, Is.EqualTo(1f)); - - // consume value, start interp, currently at start value - serverTime += 1d; // t = 2 - interp = interpolator.Update(1f, serverTime); - Assert.That(interp, Is.EqualTo(1f)); - - // interp - serverTime += 0.5d; // t = 2.5 - interp = interpolator.Update(0.5f, serverTime); - Assert.That(interp, Is.EqualTo(1.5f)); - - // reach end - serverTime += 0.5d; // t = 3 - interp = interpolator.Update(0.5f, serverTime); - Assert.That(interp, Is.EqualTo(2f)); - - // with unclamped interpolation, we continue mispredicting since the two last values are actually treated as the same. Therefore we're not stopping at "2" - serverTime += 0.5d; // t = 3.5 - interp = interpolator.Update(0.5f, serverTime); - Assert.That(interp, Is.EqualTo(2.5f)); - - serverTime += 0.5d; // t = 4 - interp = interpolator.Update(0.5f, serverTime); - Assert.That(interp, Is.EqualTo(3f)); - - // we add a measurement with an updated time - var pastServerTime = new NetworkTime(k_MockTickRate, 3.0d); - interpolator.AddMeasurement(2f, pastServerTime.Time); - - interp = interpolator.Update(0.5f, serverTime); - Assert.That(interp, Is.EqualTo(2f)); - } - } -} diff --git a/Tests/Editor/InterpolatorTests.cs.meta b/Tests/Editor/InterpolatorTests.cs.meta deleted file mode 100644 index 973fe50..0000000 --- a/Tests/Editor/InterpolatorTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a5cfbc170161c4e95ac6124ee43068b6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Messaging.meta b/Tests/Editor/Messaging.meta deleted file mode 100644 index c03aaa7..0000000 --- a/Tests/Editor/Messaging.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 55531000b0344935b665541f089df60e -timeCreated: 1630354914 \ No newline at end of file diff --git a/Tests/Editor/Messaging/DisconnectOnSendTests.cs b/Tests/Editor/Messaging/DisconnectOnSendTests.cs deleted file mode 100644 index a33e7ac..0000000 --- a/Tests/Editor/Messaging/DisconnectOnSendTests.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class DisconnectOnSendTests - { - private struct TestMessage : INetworkMessage, INetworkSerializeByMemcpy - { - public void Serialize(FastBufferWriter writer, int targetVersion) - { - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - - private class DisconnectOnSendMessageSender : INetworkMessageSender - { - public NetworkMessageManager MessageManager; - - public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData) - { - MessageManager.ClientDisconnected(clientId); - } - } - - private class TestMessageProvider : INetworkMessageProvider - { - // Keep track of what we sent - private List m_MessageList = new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessage), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - - public List GetMessages() - { - return m_MessageList; - } - } - - private TestMessageProvider m_TestMessageProvider; - private DisconnectOnSendMessageSender m_MessageSender; - private NetworkMessageManager m_MessageManager; - private ulong[] m_Clients = { 0 }; - - [SetUp] - public void SetUp() - { - m_MessageSender = new DisconnectOnSendMessageSender(); - m_TestMessageProvider = new TestMessageProvider(); - m_MessageManager = new NetworkMessageManager(m_MessageSender, this, m_TestMessageProvider); - m_MessageSender.MessageManager = m_MessageManager; - m_MessageManager.ClientConnected(0); - m_MessageManager.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0); - } - - [TearDown] - public void TearDown() - { - m_MessageManager.Dispose(); - } - - private TestMessage GetMessage() - { - return new TestMessage(); - } - - [Test] - public void WhenDisconnectIsCalledDuringSend_NoErrorsOccur() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - - // This is where an exception would be thrown and logged. - m_MessageManager.ProcessSendQueues(); - } - } -} diff --git a/Tests/Editor/Messaging/DisconnectOnSendTests.cs.meta b/Tests/Editor/Messaging/DisconnectOnSendTests.cs.meta deleted file mode 100644 index 7c030ed..0000000 --- a/Tests/Editor/Messaging/DisconnectOnSendTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7984df99de5c4b85a1b8567582d00c64 -timeCreated: 1680888331 \ No newline at end of file diff --git a/Tests/Editor/Messaging/MessageCorruptionTests.cs b/Tests/Editor/Messaging/MessageCorruptionTests.cs deleted file mode 100644 index eb2ed8a..0000000 --- a/Tests/Editor/Messaging/MessageCorruptionTests.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using NUnit.Framework; -using NUnit.Framework.Internal; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.EditorTests -{ - internal class MessageCorruptionTests - { - - private struct TestMessage : INetworkMessage, INetworkSerializeByMemcpy - { - public ForceNetworkSerializeByMemcpy Value; - public static bool Handled; - public static bool Deserialized; - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValueSafe(Value); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - Deserialized = true; - reader.ReadValueSafe(out Value); - return true; - } - - public void Handle(ref NetworkContext context) - { - Handled = true; - } - - public int Version => 0; - } - - private class TestMessageProvider : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessage), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - public enum TypeOfCorruption - { - OffsetPlus, - OffsetMinus, - CorruptBytes, - Truncated, - AdditionalGarbageData, - } - - private class TestMessageSender : INetworkMessageSender - { - - public TypeOfCorruption Corruption; - public List MessageQueue = new List(); - - public unsafe void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData) - { - switch (Corruption) - { - case TypeOfCorruption.OffsetPlus: - { - using var subWriter = new FastBufferWriter(batchData.Length + 1, Allocator.Temp); - subWriter.WriteByteSafe(0); - subWriter.WriteBytesSafe(batchData.GetUnsafePtr(), batchData.Length); - MessageQueue.Add(subWriter.ToArray()); - break; - } - case TypeOfCorruption.OffsetMinus: - { - using var subWriter = new FastBufferWriter(batchData.Length - 1, Allocator.Temp); - subWriter.WriteBytesSafe(batchData.GetUnsafePtr() + 1, batchData.Length - 1); - MessageQueue.Add(subWriter.ToArray()); - break; - } - case TypeOfCorruption.CorruptBytes: - batchData.Seek(batchData.Length - 2); - var currentByte = batchData.GetUnsafePtr()[0]; - batchData.WriteByteSafe((byte)(currentByte == 0 ? 1 : 0)); - MessageQueue.Add(batchData.ToArray()); - break; - case TypeOfCorruption.Truncated: - batchData.Truncate(batchData.Length - 1); - MessageQueue.Add(batchData.ToArray()); - break; - case TypeOfCorruption.AdditionalGarbageData: - batchData.Seek(batchData.Length); - batchData.WriteByteSafe(0); - MessageQueue.Add(batchData.ToArray()); - break; - } - } - } - - private NetworkMessageManager m_MessageManager; - private TestMessageSender m_MessageSender; - - [SetUp] - public void SetUp() - { - TestMessage.Handled = false; - TestMessage.Deserialized = false; - m_MessageSender = new TestMessageSender(); - - m_MessageManager = new NetworkMessageManager(m_MessageSender, this, new TestMessageProvider()); - - m_MessageManager.ClientConnected(0); - m_MessageManager.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0); - } - - [TearDown] - public void TearDown() - { - m_MessageManager.Dispose(); - } - - private TestMessage GetMessage() - { - return new TestMessage - { - Value = Guid.NewGuid() - }; - } - - [Test] - public unsafe void WhenPacketsAreCorrupted_TheyDontGetProcessed([Values] TypeOfCorruption typeOfCorruption) - { - m_MessageSender.Corruption = typeOfCorruption; - - switch (typeOfCorruption) - { - case TypeOfCorruption.OffsetMinus: - case TypeOfCorruption.OffsetPlus: - LogAssert.Expect(LogType.Error, new Regex("Received a packet with an invalid Magic Value\\.")); - break; - case TypeOfCorruption.Truncated: - case TypeOfCorruption.AdditionalGarbageData: - LogAssert.Expect(LogType.Error, new Regex("Received a packet with an invalid Batch Size Value\\.")); - break; - case TypeOfCorruption.CorruptBytes: - LogAssert.Expect(LogType.Error, new Regex("Received a packet with an invalid Hash Value\\.")); - break; - } - - // Dummy batch header - var batchHeader = new NetworkBatchHeader - { - BatchCount = 1 - }; - var messageHeader = new NetworkMessageHeader - { - MessageSize = (ushort)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - var message = GetMessage(); - - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(batchHeader) + - FastBufferWriter.GetWriteSize(messageHeader) + - FastBufferWriter.GetWriteSize(message)); - writer.WriteValue(batchHeader); - writer.WriteValue(messageHeader); - writer.WriteValue(message); - - // Fill out the rest of the batch header - writer.Seek(0); - batchHeader = new NetworkBatchHeader - { - Magic = NetworkBatchHeader.MagicValue, - BatchSize = writer.Length, - BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)), - BatchCount = 1 - }; - writer.WriteValue(batchHeader); - m_MessageSender.Send(0, NetworkDelivery.Reliable, writer); - - var receivedMessage = m_MessageSender.MessageQueue[0]; - m_MessageSender.MessageQueue.Clear(); - m_MessageManager.HandleIncomingData(0, new ArraySegment(receivedMessage), 0); - Assert.IsFalse(TestMessage.Deserialized); - Assert.IsFalse(TestMessage.Handled); - } - } - } -} diff --git a/Tests/Editor/Messaging/MessageCorruptionTests.cs.meta b/Tests/Editor/Messaging/MessageCorruptionTests.cs.meta deleted file mode 100644 index c6b4fc0..0000000 --- a/Tests/Editor/Messaging/MessageCorruptionTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d3c01a0b5a0e478ebc5182fe339bde04 -timeCreated: 1676997550 \ No newline at end of file diff --git a/Tests/Editor/Messaging/MessageReceivingTests.cs b/Tests/Editor/Messaging/MessageReceivingTests.cs deleted file mode 100644 index d77bf4e..0000000 --- a/Tests/Editor/Messaging/MessageReceivingTests.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using NUnit.Framework.Internal; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; - -namespace Unity.Netcode.EditorTests -{ - internal class MessageReceivingTests - { - private struct TestMessage : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public static bool Deserialized; - public static bool Handled; - public static List DeserializedValues = new List(); - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValueSafe(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - Deserialized = true; - reader.ReadValueSafe(out this); - return true; - } - - public void Handle(ref NetworkContext context) - { - Handled = true; - DeserializedValues.Add(this); - } - - public int Version => 0; - } - - private class TestMessageProvider : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessage), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - private NetworkMessageManager m_MessageManager; - - [SetUp] - public void SetUp() - { - TestMessage.Deserialized = false; - TestMessage.Handled = false; - TestMessage.DeserializedValues.Clear(); - - m_MessageManager = new NetworkMessageManager(new NopMessageSender(), this, new TestMessageProvider()); - m_MessageManager.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0); - } - - [TearDown] - public void TearDown() - { - m_MessageManager.Dispose(); - } - - private TestMessage GetMessage() - { - var random = new Random(); - return new TestMessage - { - A = random.Next(), - B = random.Next(), - C = random.Next(), - }; - } - - [Test] - public void WhenHandlingAMessage_ReceiveMethodIsCalled() - { - var messageHeader = new NetworkMessageHeader - { - MessageSize = (ushort)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - var message = GetMessage(); - - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(message)); - writer.WriteValue(message); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - m_MessageManager.HandleMessage(messageHeader, reader, 0, 0, 0); - Assert.IsTrue(TestMessage.Deserialized); - Assert.IsTrue(TestMessage.Handled); - Assert.AreEqual(1, TestMessage.DeserializedValues.Count); - Assert.AreEqual(message, TestMessage.DeserializedValues[0]); - } - } - } - - [Test] - public unsafe void WhenHandlingIncomingData_ReceiveIsNotCalledBeforeProcessingIncomingMessageQueue() - { - var batchHeader = new NetworkBatchHeader - { - BatchCount = 1 - }; - var messageHeader = new NetworkMessageHeader - { - MessageSize = (ushort)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - var message = GetMessage(); - - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(batchHeader) + - FastBufferWriter.GetWriteSize(messageHeader) + - FastBufferWriter.GetWriteSize(message)); - writer.WriteValue(batchHeader); - writer.WriteValue(messageHeader); - writer.WriteValue(message); - - // Fill out the rest of the batch header - writer.Seek(0); - batchHeader = new NetworkBatchHeader - { - Magic = NetworkBatchHeader.MagicValue, - BatchSize = writer.Length, - BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)), - BatchCount = 1 - }; - writer.WriteValue(batchHeader); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - m_MessageManager.HandleIncomingData(0, new ArraySegment(writer.ToArray()), 0); - Assert.IsFalse(TestMessage.Deserialized); - Assert.IsFalse(TestMessage.Handled); - Assert.IsEmpty(TestMessage.DeserializedValues); - } - } - } - - [Test] - public unsafe void WhenReceivingAMessageAndProcessingMessageQueue_ReceiveMethodIsCalled() - { - var batchHeader = new NetworkBatchHeader - { - BatchCount = 1 - }; - var messageHeader = new NetworkMessageHeader - { - MessageSize = (uint)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - var message = GetMessage(); - - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(batchHeader); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize); - writer.WriteValueSafe(message); - - // Fill out the rest of the batch header - writer.Seek(0); - batchHeader = new NetworkBatchHeader - { - Magic = NetworkBatchHeader.MagicValue, - BatchSize = writer.Length, - BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)), - BatchCount = 1 - }; - writer.WriteValue(batchHeader); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - m_MessageManager.HandleIncomingData(0, new ArraySegment(writer.ToArray()), 0); - m_MessageManager.ProcessIncomingMessageQueue(); - Assert.IsTrue(TestMessage.Deserialized); - Assert.IsTrue(TestMessage.Handled); - Assert.AreEqual(1, TestMessage.DeserializedValues.Count); - Assert.AreEqual(message, TestMessage.DeserializedValues[0]); - } - } - } - - [Test] - public unsafe void WhenReceivingMultipleMessagesAndProcessingMessageQueue_ReceiveMethodIsCalledMultipleTimes() - { - var batchHeader = new NetworkBatchHeader - { - BatchCount = 2 - }; - var messageHeader = new NetworkMessageHeader - { - MessageSize = (ushort)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - var message = GetMessage(); - var message2 = GetMessage(); - - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(batchHeader); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize); - writer.WriteValueSafe(message); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageType); - BytePacker.WriteValueBitPacked(writer, messageHeader.MessageSize); - writer.WriteValueSafe(message2); - - // Fill out the rest of the batch header - writer.Seek(0); - batchHeader = new NetworkBatchHeader - { - Magic = NetworkBatchHeader.MagicValue, - BatchSize = writer.Length, - BatchHash = XXHash.Hash64(writer.GetUnsafePtr() + sizeof(NetworkBatchHeader), writer.Length - sizeof(NetworkBatchHeader)), - BatchCount = 2 - }; - writer.WriteValue(batchHeader); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - m_MessageManager.HandleIncomingData(0, new ArraySegment(writer.ToArray()), 0); - Assert.IsFalse(TestMessage.Deserialized); - Assert.IsFalse(TestMessage.Handled); - Assert.IsEmpty(TestMessage.DeserializedValues); - - m_MessageManager.ProcessIncomingMessageQueue(); - Assert.IsTrue(TestMessage.Deserialized); - Assert.IsTrue(TestMessage.Handled); - Assert.AreEqual(2, TestMessage.DeserializedValues.Count); - Assert.AreEqual(message, TestMessage.DeserializedValues[0]); - Assert.AreEqual(message2, TestMessage.DeserializedValues[1]); - } - } - } - } -} diff --git a/Tests/Editor/Messaging/MessageReceivingTests.cs.meta b/Tests/Editor/Messaging/MessageReceivingTests.cs.meta deleted file mode 100644 index 45178e3..0000000 --- a/Tests/Editor/Messaging/MessageReceivingTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cbc8fb6cf75f52d46a5d74971ce4b240 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Messaging/MessageRegistrationTests.cs b/Tests/Editor/Messaging/MessageRegistrationTests.cs deleted file mode 100644 index 6689894..0000000 --- a/Tests/Editor/Messaging/MessageRegistrationTests.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class MessageRegistrationTests - { - private struct TestMessageOne : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValue(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - - private struct TestMessageTwo : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValue(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - private class TestMessageProviderOne : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessageOne), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - }, - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessageTwo), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - private struct TestMessageThree : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValue(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - private class TestMessageProviderTwo : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessageThree), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - private struct TestMessageFour : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public void Serialize(FastBufferWriter writer, int targetVersion) - { - writer.WriteValue(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - private class TestMessageProviderThree : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessageFour), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - [Test] - public void WhenCreatingMessageSystem_OnlyProvidedTypesAreRegistered() - { - var sender = new NopMessageSender(); - - using var systemOne = new NetworkMessageManager(sender, null, new TestMessageProviderOne()); - using var systemTwo = new NetworkMessageManager(sender, null, new TestMessageProviderTwo()); - using var systemThree = new NetworkMessageManager(sender, null, new TestMessageProviderThree()); - - using (systemOne) - using (systemTwo) - using (systemThree) - { - Assert.AreEqual(2, systemOne.MessageHandlerCount); - Assert.AreEqual(1, systemTwo.MessageHandlerCount); - Assert.AreEqual(1, systemThree.MessageHandlerCount); - - Assert.Contains(typeof(TestMessageOne), systemOne.MessageTypes); - Assert.Contains(typeof(TestMessageTwo), systemOne.MessageTypes); - Assert.Contains(typeof(TestMessageThree), systemTwo.MessageTypes); - Assert.Contains(typeof(TestMessageFour), systemThree.MessageTypes); - } - } - - [Test] - public void WhenCreatingMessageSystem_BoundTypeMessageHandlersAreRegistered() - { - var sender = new NopMessageSender(); - - using var systemOne = new NetworkMessageManager(sender, null, new TestMessageProviderOne()); - using var systemTwo = new NetworkMessageManager(sender, null, new TestMessageProviderTwo()); - using var systemThree = new NetworkMessageManager(sender, null, new TestMessageProviderThree()); - - using (systemOne) - using (systemTwo) - using (systemThree) - { - NetworkMessageManager.MessageHandler handlerOne = NetworkMessageManager.ReceiveMessage; - NetworkMessageManager.MessageHandler handlerTwo = NetworkMessageManager.ReceiveMessage; - NetworkMessageManager.MessageHandler handlerThree = NetworkMessageManager.ReceiveMessage; - NetworkMessageManager.MessageHandler handlerFour = NetworkMessageManager.ReceiveMessage; - - Assert.AreEqual(handlerOne, systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageOne))]); - Assert.AreEqual(handlerTwo, systemOne.MessageHandlers[systemOne.GetMessageType(typeof(TestMessageTwo))]); - Assert.AreEqual(handlerThree, systemTwo.MessageHandlers[systemTwo.GetMessageType(typeof(TestMessageThree))]); - Assert.AreEqual(handlerFour, systemThree.MessageHandlers[systemThree.GetMessageType(typeof(TestMessageFour))]); - } - } - } -} diff --git a/Tests/Editor/Messaging/MessageRegistrationTests.cs.meta b/Tests/Editor/Messaging/MessageRegistrationTests.cs.meta deleted file mode 100644 index 860ab64..0000000 --- a/Tests/Editor/Messaging/MessageRegistrationTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 03e7cc2b6f0c5c540a529429f48529f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Messaging/MessageSendingTests.cs b/Tests/Editor/Messaging/MessageSendingTests.cs deleted file mode 100644 index 84967b7..0000000 --- a/Tests/Editor/Messaging/MessageSendingTests.cs +++ /dev/null @@ -1,369 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using NUnit.Framework; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; -using UnityEngine; -using UnityEngine.TestTools; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class MessageSendingTests - { - private struct TestMessage : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public static bool Serialized; - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - Serialized = true; - writer.WriteValueSafe(this); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - return true; - } - - public void Handle(ref NetworkContext context) - { - } - - public int Version => 0; - } - - private class TestMessageSender : INetworkMessageSender - { - public List MessageQueue = new List(); - - public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData) - { - MessageQueue.Add(batchData.ToArray()); - } - } - - private class TestMessageProvider : INetworkMessageProvider, IDisposable - { - // Keep track of what we sent - private List> m_CachedMessages = new List>(); - - public void Dispose() - { - foreach (var cachedItem in m_CachedMessages) - { - // Clear out any references to NetworkMessageManager.MessageWithHandlers - cachedItem.Clear(); - } - - m_CachedMessages.Clear(); - } - - public List GetMessages() - { - var messageList = new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessage), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - // Track messages sent - m_CachedMessages.Add(messageList); - return messageList; - } - } - - private TestMessageProvider m_TestMessageProvider; - private TestMessageSender m_MessageSender; - private NetworkMessageManager m_MessageManager; - private ulong[] m_Clients = { 0 }; - - [SetUp] - public void SetUp() - { - TestMessage.Serialized = false; - m_MessageSender = new TestMessageSender(); - m_TestMessageProvider = new TestMessageProvider(); - m_MessageManager = new NetworkMessageManager(m_MessageSender, this, m_TestMessageProvider); - m_MessageManager.ClientConnected(0); - m_MessageManager.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0); - } - - [TearDown] - public void TearDown() - { - m_TestMessageProvider.Dispose(); - m_MessageManager.Dispose(); - } - - private TestMessage GetMessage() - { - var random = new Random(); - return new TestMessage - { - A = random.Next(), - B = random.Next(), - C = random.Next(), - }; - } - - [Test] - public void WhenSendingMessage_SerializeIsCalled() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - Assert.IsTrue(TestMessage.Serialized); - } - - [Test] - public void WhenSendingMessage_NothingIsSentBeforeProcessingSendQueue() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - Assert.IsEmpty(m_MessageSender.MessageQueue); - } - - [Test] - public void WhenProcessingSendQueue_MessageIsSent() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenSendingMultipleMessages_MessagesAreBatched() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenNotExceedingBatchSize_NewBatchesAreNotCreated() - { - var message = GetMessage(); - var size = UnsafeUtility.SizeOf() + 2; // MessageHeader packed with this message will be 2 bytes - for (var i = 0; i < (m_MessageManager.NonFragmentedMessageMaxSize - UnsafeUtility.SizeOf()) / size; ++i) - { - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - } - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenExceedingBatchSize_NewBatchesAreCreated([Values(500, 1000, 1300, 2000)] int maxMessageSize) - { - var message = GetMessage(); - m_MessageManager.NonFragmentedMessageMaxSize = maxMessageSize; - var size = UnsafeUtility.SizeOf() + 2; // MessageHeader packed with this message will be 2 bytes - for (var i = 0; i < ((m_MessageManager.NonFragmentedMessageMaxSize - UnsafeUtility.SizeOf()) / size) + 1; ++i) - { - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - } - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(2, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenExceedingPerClientBatchSizeLessThanDefault_NewBatchesAreCreated([Values(500, 1000, 1300, 2000)] int maxMessageSize) - { - var message = GetMessage(); - m_MessageManager.NonFragmentedMessageMaxSize = maxMessageSize * 5; - var clients = new ulong[] { 0, 1, 2 }; - m_MessageManager.ClientConnected(1); - m_MessageManager.ClientConnected(2); - m_MessageManager.SetVersion(1, XXHash.Hash32(typeof(TestMessage).FullName), 0); - m_MessageManager.SetVersion(2, XXHash.Hash32(typeof(TestMessage).FullName), 0); - - for (var i = 0; i < clients.Length; ++i) - { - m_MessageManager.PeerMTUSizes[clients[i]] = maxMessageSize * (i + 1); - } - - var size = UnsafeUtility.SizeOf() + 2; // MessageHeader packed with this message will be 2 bytes - for (var i = 0; i < clients.Length; ++i) - { - for (var j = 0; j < ((m_MessageManager.PeerMTUSizes[clients[i]] - UnsafeUtility.SizeOf()) / size) + 1; ++j) - { - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, clients[i]); - } - } - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(2 * clients.Length, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenExceedingPerClientBatchSizeGreaterThanDefault_OnlyOneNewBatcheIsCreated([Values(500, 1000, 1300, 2000)] int maxMessageSize) - { - var message = GetMessage(); - m_MessageManager.NonFragmentedMessageMaxSize = 128; - var clients = new ulong[] { 0, 1, 2 }; - m_MessageManager.ClientConnected(1); - m_MessageManager.ClientConnected(2); - m_MessageManager.SetVersion(1, XXHash.Hash32(typeof(TestMessage).FullName), 0); - m_MessageManager.SetVersion(2, XXHash.Hash32(typeof(TestMessage).FullName), 0); - - for (var i = 0; i < clients.Length; ++i) - { - m_MessageManager.PeerMTUSizes[clients[i]] = maxMessageSize * (i + 1); - } - - var size = UnsafeUtility.SizeOf() + 2; // MessageHeader packed with this message will be 2 bytes - for (var i = 0; i < clients.Length; ++i) - { - for (var j = 0; j < ((m_MessageManager.PeerMTUSizes[clients[i]] - UnsafeUtility.SizeOf()) / size) + 1; ++j) - { - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, clients[i]); - } - } - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(2 * clients.Length, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenExceedingMTUSizeWithFragmentedDelivery_NewBatchesAreNotCreated([Values(500, 1000, 1300, 2000)] int maxMessageSize) - { - var message = GetMessage(); - m_MessageManager.NonFragmentedMessageMaxSize = maxMessageSize; - var size = UnsafeUtility.SizeOf() + 2; // MessageHeader packed with this message will be 2 bytes - for (var i = 0; i < ((m_MessageManager.NonFragmentedMessageMaxSize - UnsafeUtility.SizeOf()) / size) + 1; ++i) - { - m_MessageManager.SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, m_Clients); - } - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenSwitchingDelivery_NewBatchesAreCreated() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Unreliable, m_Clients); - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(2, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenSwitchingChannel_NewBatchesAreNotCreated() - { - var message = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - - m_MessageManager.ProcessSendQueues(); - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - } - - [Test] - public void WhenSendingMessaged_SentDataIsCorrect() - { - var message = GetMessage(); - var message2 = GetMessage(); - m_MessageManager.SendMessage(ref message, NetworkDelivery.Reliable, m_Clients); - m_MessageManager.SendMessage(ref message2, NetworkDelivery.Reliable, m_Clients); - - m_MessageManager.ProcessSendQueues(); - var reader = new FastBufferReader(m_MessageSender.MessageQueue[0], Allocator.Temp); - using (reader) - { - reader.ReadValueSafe(out NetworkBatchHeader header); - Assert.AreEqual(2, header.BatchCount); - - NetworkMessageHeader messageHeader; - - ByteUnpacker.ReadValueBitPacked(reader, out messageHeader.MessageType); - ByteUnpacker.ReadValueBitPacked(reader, out messageHeader.MessageSize); - - Assert.AreEqual(m_MessageManager.GetMessageType(typeof(TestMessage)), messageHeader.MessageType); - Assert.AreEqual(UnsafeUtility.SizeOf(), messageHeader.MessageSize); - reader.ReadValueSafe(out TestMessage receivedMessage); - Assert.AreEqual(message, receivedMessage); - - ByteUnpacker.ReadValueBitPacked(reader, out messageHeader.MessageType); - ByteUnpacker.ReadValueBitPacked(reader, out messageHeader.MessageSize); - - Assert.AreEqual(m_MessageManager.GetMessageType(typeof(TestMessage)), messageHeader.MessageType); - Assert.AreEqual(UnsafeUtility.SizeOf(), messageHeader.MessageSize); - reader.ReadValueSafe(out TestMessage receivedMessage2); - Assert.AreEqual(message2, receivedMessage2); - } - } - - private class TestNoHandlerMessageProvider : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(TestMessage), - Handler = null, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - [Test] - public void WhenReceivingAMessageWithoutAHandler_ExceptionIsLogged() - { - // If a NetworkMessageManager already exists then dispose of it before creating a new NetworkMessageManager (otherwise memory leak) - if (m_MessageManager != null) - { - m_MessageManager.Dispose(); - m_MessageManager = null; - } - - // Since m_MessageManager is disposed during teardown we don't need to worry about that here. - m_MessageManager = new NetworkMessageManager(new NopMessageSender(), this, new TestNoHandlerMessageProvider()); - m_MessageManager.ClientConnected(0); - - var messageHeader = new NetworkMessageHeader - { - MessageSize = (ushort)UnsafeUtility.SizeOf(), - MessageType = m_MessageManager.GetMessageType(typeof(TestMessage)), - }; - - var message = GetMessage(); - - var writer = new FastBufferWriter(m_MessageManager.NonFragmentedMessageMaxSize, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(message)); - writer.WriteValue(message); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - m_MessageManager.HandleMessage(messageHeader, reader, 0, 0, 0); - LogAssert.Expect(LogType.Exception, new Regex(".*HandlerNotRegisteredException.*")); - } - } - } - } -} diff --git a/Tests/Editor/Messaging/MessageSendingTests.cs.meta b/Tests/Editor/Messaging/MessageSendingTests.cs.meta deleted file mode 100644 index 8589132..0000000 --- a/Tests/Editor/Messaging/MessageSendingTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ea2fc218c5e07c54795fc9bed4a6a62c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Messaging/MessageVersioningTests.cs b/Tests/Editor/Messaging/MessageVersioningTests.cs deleted file mode 100644 index 222c08b..0000000 --- a/Tests/Editor/Messaging/MessageVersioningTests.cs +++ /dev/null @@ -1,503 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using NUnit.Framework.Internal; - -namespace Unity.Netcode.EditorTests -{ - internal class MessageVersioningTests - { - public static int SentVersion; - public static int ReceivedVersion; - - private const int k_DefaultB = 5; - private const int k_DefaultC = 10; - private const int k_DefaultD = 15; - private const long k_DefaultE = 20; - - private struct VersionedTestMessageV0 : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public static bool Serialized; - public static bool Deserialized; - public static bool Handled; - public static List DeserializedValues = new List(); - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - SentVersion = Version; - Serialized = true; - writer.WriteValueSafe(A); - writer.WriteValueSafe(B); - writer.WriteValueSafe(C); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - ReceivedVersion = Version; - Deserialized = true; - reader.ReadValueSafe(out A); - reader.ReadValueSafe(out B); - reader.ReadValueSafe(out C); - return true; - } - - public void Handle(ref NetworkContext context) - { - Handled = true; - DeserializedValues.Add(this); - } - - public int Version => 0; - } - - private struct VersionedTestMessageV1 : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public int B; - public int C; - public int D; - public static bool Serialized; - public static bool Deserialized; - public static bool Downgraded; - public static bool Upgraded; - public static bool Handled; - public static List DeserializedValues = new List(); - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - if (targetVersion < Version) - { - Downgraded = true; - var v0 = new VersionedTestMessageV0 { A = A, B = B, C = C }; - v0.Serialize(writer, targetVersion); - return; - } - SentVersion = Version; - Serialized = true; - writer.WriteValueSafe(C); - writer.WriteValueSafe(D); - writer.WriteValueSafe(A); - writer.WriteValueSafe(B); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - if (receivedMessageVersion < Version) - { - var v0 = new VersionedTestMessageV0(); - v0.Deserialize(reader, ref context, receivedMessageVersion); - A = v0.A; - B = v0.B; - C = v0.C; - D = k_DefaultD; - Upgraded = true; - return true; - } - ReceivedVersion = Version; - Deserialized = true; - reader.ReadValueSafe(out C); - reader.ReadValueSafe(out D); - reader.ReadValueSafe(out A); - reader.ReadValueSafe(out B); - return true; - } - - public void Handle(ref NetworkContext context) - { - Handled = true; - DeserializedValues.Add(this); - } - - public int Version => 1; - } - - private struct VersionedTestMessage : INetworkMessage, INetworkSerializeByMemcpy - { - public int A; - public float D; - public long E; - public static bool Serialized; - public static bool Deserialized; - public static bool Downgraded; - public static bool Upgraded; - public static bool Handled; - public static List DeserializedValues = new List(); - - public void Serialize(FastBufferWriter writer, int targetVersion) - { - if (targetVersion < Version) - { - Downgraded = true; - var v1 = new VersionedTestMessageV1 { A = A, B = k_DefaultB, C = k_DefaultC, D = (int)D }; - v1.Serialize(writer, targetVersion); - return; - } - SentVersion = Version; - Serialized = true; - writer.WriteValueSafe(D); - writer.WriteValueSafe(A); - writer.WriteValueSafe(E); - } - - public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion) - { - if (receivedMessageVersion < Version) - { - var v1 = new VersionedTestMessageV1(); - v1.Deserialize(reader, ref context, receivedMessageVersion); - A = v1.A; - D = v1.D; - E = k_DefaultE; - Upgraded = true; - return true; - } - ReceivedVersion = Version; - Deserialized = true; - reader.ReadValueSafe(out D); - reader.ReadValueSafe(out A); - reader.ReadValueSafe(out E); - return true; - } - - public void Handle(ref NetworkContext context) - { - Handled = true; - DeserializedValues.Add(this); - } - - public int Version => 2; - } - - private class TestMessageProviderV0 : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(VersionedTestMessageV0), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - private class TestMessageProviderV1 : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(VersionedTestMessageV1), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - private class TestMessageProviderV2 : INetworkMessageProvider - { - public List GetMessages() - { - return new List - { - new NetworkMessageManager.MessageWithHandler - { - MessageType = typeof(VersionedTestMessage), - Handler = NetworkMessageManager.ReceiveMessage, - GetVersion = NetworkMessageManager.CreateMessageAndGetVersion - } - }; - } - } - - private class TestMessageSender : INetworkMessageSender - { - public List MessageQueue = new List(); - - public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData) - { - MessageQueue.Add(batchData.ToArray()); - } - } - - private NetworkMessageManager m_MessageManagerV0; - private NetworkMessageManager m_MessageManagerV1; - private NetworkMessageManager m_MessageManagerV2; - private TestMessageSender m_MessageSender; - - private void CreateFakeClients(NetworkMessageManager system, uint hash) - { - // Create three fake clients for each NetworkMessageManager - // client 0 has version 0, client 1 has version 1, and client 2 has version 2 - system.ClientConnected(0); - system.ClientConnected(1); - system.ClientConnected(2); - system.SetVersion(0, hash, 0); - system.SetVersion(1, hash, 1); - system.SetVersion(2, hash, 2); - } - - [SetUp] - public void SetUp() - { - VersionedTestMessageV0.Serialized = false; - VersionedTestMessageV0.Deserialized = false; - VersionedTestMessageV0.Handled = false; - VersionedTestMessageV0.DeserializedValues.Clear(); - VersionedTestMessageV1.Serialized = false; - VersionedTestMessageV1.Deserialized = false; - VersionedTestMessageV1.Downgraded = false; - VersionedTestMessageV1.Upgraded = false; - VersionedTestMessageV1.Handled = false; - VersionedTestMessageV1.DeserializedValues.Clear(); - VersionedTestMessage.Serialized = false; - VersionedTestMessage.Deserialized = false; - VersionedTestMessage.Downgraded = false; - VersionedTestMessage.Upgraded = false; - VersionedTestMessage.Handled = false; - VersionedTestMessage.DeserializedValues.Clear(); - m_MessageSender = new TestMessageSender(); - - m_MessageManagerV0 = new NetworkMessageManager(m_MessageSender, this, new TestMessageProviderV0()); - m_MessageManagerV1 = new NetworkMessageManager(m_MessageSender, this, new TestMessageProviderV1()); - m_MessageManagerV2 = new NetworkMessageManager(m_MessageSender, this, new TestMessageProviderV2()); - - CreateFakeClients(m_MessageManagerV0, XXHash.Hash32(typeof(VersionedTestMessageV0).FullName)); - CreateFakeClients(m_MessageManagerV1, XXHash.Hash32(typeof(VersionedTestMessageV1).FullName)); - CreateFakeClients(m_MessageManagerV2, XXHash.Hash32(typeof(VersionedTestMessage).FullName)); - - // Make sure that all three messages got the same IDs... - Assert.AreEqual( - m_MessageManagerV0.GetMessageType(typeof(VersionedTestMessageV0)), - m_MessageManagerV1.GetMessageType(typeof(VersionedTestMessageV1))); - Assert.AreEqual( - m_MessageManagerV0.GetMessageType(typeof(VersionedTestMessageV0)), - m_MessageManagerV2.GetMessageType(typeof(VersionedTestMessage))); - } - - [TearDown] - public void TearDown() - { - m_MessageManagerV0.Dispose(); - m_MessageManagerV1.Dispose(); - m_MessageManagerV2.Dispose(); - } - - private VersionedTestMessageV0 GetMessage_v0() - { - var random = new Random(); - return new VersionedTestMessageV0 - { - A = random.Next(), - B = random.Next(), - C = random.Next(), - }; - } - - private VersionedTestMessageV1 GetMessage_v1() - { - var random = new Random(); - return new VersionedTestMessageV1 - { - A = random.Next(), - B = random.Next(), - C = random.Next(), - D = random.Next(), - }; - } - - private VersionedTestMessage GetMessage_v2() - { - var random = new Random(); - return new VersionedTestMessage - { - A = random.Next(), - D = (float)(random.NextDouble() * 10000), - E = ((long)random.Next() << 32) + random.Next() - }; - } - - public void CheckPostSendExpectations(int sourceLocalVersion, int remoteVersion) - { - Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 0, VersionedTestMessageV0.Serialized); - Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 1, VersionedTestMessageV1.Serialized); - Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 2, VersionedTestMessage.Serialized); - Assert.AreEqual(sourceLocalVersion >= 1 && remoteVersion < 1, VersionedTestMessageV1.Downgraded); - Assert.AreEqual(sourceLocalVersion >= 2 && remoteVersion < 2, VersionedTestMessage.Downgraded); - - Assert.AreEqual(1, m_MessageSender.MessageQueue.Count); - Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion), SentVersion); - } - - public void CheckPostReceiveExpectations(int sourceLocalVersion, int remoteVersion) - { - Assert.AreEqual(SentVersion == 0, VersionedTestMessageV0.Deserialized); - Assert.AreEqual(SentVersion == 1, VersionedTestMessageV1.Deserialized); - Assert.AreEqual(SentVersion == 2, VersionedTestMessage.Deserialized); - Assert.AreEqual(remoteVersion >= 1 && sourceLocalVersion < 1, VersionedTestMessageV1.Upgraded); - Assert.AreEqual(remoteVersion >= 2 && sourceLocalVersion < 2, VersionedTestMessage.Upgraded); - - Assert.AreEqual((remoteVersion == 0 ? 1 : 0), VersionedTestMessageV0.DeserializedValues.Count); - Assert.AreEqual((remoteVersion == 1 ? 1 : 0), VersionedTestMessageV1.DeserializedValues.Count); - Assert.AreEqual((remoteVersion == 2 ? 1 : 0), VersionedTestMessage.DeserializedValues.Count); - - Assert.AreEqual(SentVersion, ReceivedVersion); - } - - private void SendMessageWithVersions(T message, int fromVersion, int toVersion) where T : unmanaged, INetworkMessage - { - NetworkMessageManager sendSystem; - switch (fromVersion) - { - case 0: sendSystem = m_MessageManagerV0; break; - case 1: sendSystem = m_MessageManagerV1; break; - default: sendSystem = m_MessageManagerV2; break; - } - sendSystem.SendMessage(ref message, NetworkDelivery.Reliable, (ulong)toVersion); - sendSystem.ProcessSendQueues(); - CheckPostSendExpectations(fromVersion, toVersion); - - NetworkMessageManager receiveSystem; - switch (toVersion) - { - case 0: receiveSystem = m_MessageManagerV0; break; - case 1: receiveSystem = m_MessageManagerV1; break; - default: receiveSystem = m_MessageManagerV2; break; - } - receiveSystem.HandleIncomingData((ulong)fromVersion, new ArraySegment(m_MessageSender.MessageQueue[0]), 0.0f); - receiveSystem.ProcessIncomingMessageQueue(); - CheckPostReceiveExpectations(fromVersion, toVersion); - - m_MessageSender.MessageQueue.Clear(); - } - - [Test] - public void WhenSendingV0ToV0_DataIsReceivedCorrectly() - { - var message = GetMessage_v0(); - - SendMessageWithVersions(message, 0, 0); - - var receivedMessage = VersionedTestMessageV0.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(message.B, receivedMessage.B); - Assert.AreEqual(message.C, receivedMessage.C); - } - - [Test] - public void WhenSendingV0ToV1_DataIsReceivedCorrectly() - { - var message = GetMessage_v0(); - - SendMessageWithVersions(message, 0, 1); - - var receivedMessage = VersionedTestMessageV1.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(message.B, receivedMessage.B); - Assert.AreEqual(message.C, receivedMessage.C); - Assert.AreEqual(k_DefaultD, receivedMessage.D); - } - - [Test] - public void WhenSendingV0ToV2_DataIsReceivedCorrectly() - { - var message = GetMessage_v0(); - - SendMessageWithVersions(message, 0, 2); - - var receivedMessage = VersionedTestMessage.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual((float)k_DefaultD, receivedMessage.D); - Assert.AreEqual(k_DefaultE, receivedMessage.E); - } - - [Test] - public void WhenSendingV1ToV0_DataIsReceivedCorrectly() - { - var message = GetMessage_v1(); - - SendMessageWithVersions(message, 1, 0); - - var receivedMessage = VersionedTestMessageV0.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(message.B, receivedMessage.B); - Assert.AreEqual(message.C, receivedMessage.C); - } - - [Test] - public void WhenSendingV1ToV1_DataIsReceivedCorrectly() - { - var message = GetMessage_v1(); - - SendMessageWithVersions(message, 1, 1); - - var receivedMessage = VersionedTestMessageV1.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(message.B, receivedMessage.B); - Assert.AreEqual(message.C, receivedMessage.C); - Assert.AreEqual(message.D, receivedMessage.D); - } - - [Test] - public void WhenSendingV1ToV2_DataIsReceivedCorrectly() - { - var message = GetMessage_v1(); - - SendMessageWithVersions(message, 1, 2); - - var receivedMessage = VersionedTestMessage.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual((float)message.D, receivedMessage.D); - Assert.AreEqual(k_DefaultE, receivedMessage.E); - } - - [Test] - public void WhenSendingV2ToV0_DataIsReceivedCorrectly() - { - var message = GetMessage_v2(); - - SendMessageWithVersions(message, 2, 0); - - var receivedMessage = VersionedTestMessageV0.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(k_DefaultB, receivedMessage.B); - Assert.AreEqual(k_DefaultC, receivedMessage.C); - } - - [Test] - public void WhenSendingV2ToV1_DataIsReceivedCorrectly() - { - var message = GetMessage_v2(); - - SendMessageWithVersions(message, 2, 1); - - var receivedMessage = VersionedTestMessageV1.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(k_DefaultB, receivedMessage.B); - Assert.AreEqual(k_DefaultC, receivedMessage.C); - Assert.AreEqual((int)message.D, receivedMessage.D); - } - - [Test] - public void WhenSendingV2ToV2_DataIsReceivedCorrectly() - { - var message = GetMessage_v2(); - - SendMessageWithVersions(message, 2, 2); - - var receivedMessage = VersionedTestMessage.DeserializedValues[0]; - Assert.AreEqual(message.A, receivedMessage.A); - Assert.AreEqual(message.D, receivedMessage.D); - Assert.AreEqual(message.E, receivedMessage.E); - } - } -} diff --git a/Tests/Editor/Messaging/MessageVersioningTests.cs.meta b/Tests/Editor/Messaging/MessageVersioningTests.cs.meta deleted file mode 100644 index 11b7f62..0000000 --- a/Tests/Editor/Messaging/MessageVersioningTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: eac9a654aacb4faf91128c9ab6024543 -timeCreated: 1667326658 \ No newline at end of file diff --git a/Tests/Editor/Messaging/NopMessageSender.cs b/Tests/Editor/Messaging/NopMessageSender.cs deleted file mode 100644 index 3f5a35b..0000000 --- a/Tests/Editor/Messaging/NopMessageSender.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Unity.Netcode.EditorTests -{ - internal class NopMessageSender : INetworkMessageSender - { - public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData) - { - } - } -} diff --git a/Tests/Editor/Messaging/NopMessageSender.cs.meta b/Tests/Editor/Messaging/NopMessageSender.cs.meta deleted file mode 100644 index 321f2a7..0000000 --- a/Tests/Editor/Messaging/NopMessageSender.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 817c58672ba39a74da57082ed176956e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Metrics.meta b/Tests/Editor/Metrics.meta deleted file mode 100644 index bc962b1..0000000 --- a/Tests/Editor/Metrics.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 87ddfad8823c4fe192fff56b7acc241b -timeCreated: 1629386688 \ No newline at end of file diff --git a/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs b/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs deleted file mode 100644 index 82b88ec..0000000 --- a/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System; -using System.Linq; -using System.Reflection; -using NUnit.Framework; -using Unity.Multiplayer.Tools.MetricTypes; -using Unity.Multiplayer.Tools.NetStats; - -namespace Unity.Netcode.EditorTests.Metrics -{ - internal class NetworkMetricsRegistrationTests - { - private static Type[] s_MetricTypes = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(x => x.GetTypes()) - .Where(x => x.GetInterfaces().Contains(typeof(INetworkMetricEvent))) - .ToArray(); - - [TestCaseSource(nameof(s_MetricTypes))] - [Ignore("Disable test while we reevaluate the assumption that INetworkMetricEvent interfaces must be reported from MLAPI.")] - public void ValidateThatAllMetricTypesAreRegistered(Type metricType) - { - var dispatcher = new NetworkMetrics().Dispatcher as MetricDispatcher; - Assert.NotNull(dispatcher); - - var collection = typeof(MetricDispatcher) - .GetField("m_Collection", BindingFlags.NonPublic | BindingFlags.Instance)? - .GetValue(dispatcher) as MetricCollection; - Assert.NotNull(collection); - - Assert.That( - collection.Metrics.OfType(), - Has.Exactly(2).Matches( - eventMetric => - { - var eventType = eventMetric.GetType().GetGenericArguments()?.FirstOrDefault(); - return eventType == metricType; - })); - } - } -} - -#endif diff --git a/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs.meta b/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs.meta deleted file mode 100644 index 89ebdab..0000000 --- a/Tests/Editor/Metrics/NetworkMetricsRegistrationTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: af741f5e3d4f5544eaa68bb9bcaf54c6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/NetworkBehaviourTests.cs b/Tests/Editor/NetworkBehaviourTests.cs deleted file mode 100644 index 29c8279..0000000 --- a/Tests/Editor/NetworkBehaviourTests.cs +++ /dev/null @@ -1,79 +0,0 @@ -using NUnit.Framework; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.EditorTests -{ - internal class NetworkBehaviourTests - { - [Test] - public void HasNetworkObjectTest() - { - var gameObject = new GameObject(nameof(HasNetworkObjectTest)); - var networkBehaviour = gameObject.AddComponent(); - - Assert.That(networkBehaviour.HasNetworkObject, Is.False); - - var networkObject = gameObject.AddComponent(); - - Assert.That(networkBehaviour.HasNetworkObject, Is.True); - - Object.DestroyImmediate(networkObject); - - Assert.That(networkBehaviour.HasNetworkObject, Is.False); - - // Cleanup - Object.DestroyImmediate(gameObject); - } - - [Test] - public void AccessNetworkObjectTest() - { - var gameObject = new GameObject(nameof(AccessNetworkObjectTest)); - var networkBehaviour = gameObject.AddComponent(); - - Assert.That(networkBehaviour.NetworkObject, Is.Null); - - var networkObject = gameObject.AddComponent(); - - Assert.That(networkBehaviour.NetworkObject, Is.EqualTo(networkObject)); - - Object.DestroyImmediate(networkObject); - - Assert.That(networkBehaviour.NetworkObject, Is.Null); - - // Cleanup - Object.DestroyImmediate(gameObject); - } - - [Test] - public void GivenClassDerivesFromNetworkBehaviour_GetTypeNameReturnsCorrectValue() - { - var gameObject = new GameObject(nameof(GivenClassDerivesFromNetworkBehaviour_GetTypeNameReturnsCorrectValue)); - var networkBehaviour = gameObject.AddComponent(); - - Assert.AreEqual(nameof(EmptyNetworkBehaviour), networkBehaviour.__getTypeName()); - } - - [Test] - public void GivenClassDerivesFromNetworkBehaviourDerivedClass_GetTypeNameReturnsCorrectValue() - { - var gameObject = new GameObject(nameof(GivenClassDerivesFromNetworkBehaviourDerivedClass_GetTypeNameReturnsCorrectValue)); - var networkBehaviour = gameObject.AddComponent(); - - Assert.AreEqual(nameof(DerivedNetworkBehaviour), networkBehaviour.__getTypeName()); - } - - // Note: in order to repro https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues/1078 - // this child class must be defined before its parent to assure it is processed first by ILPP - internal class DerivedNetworkBehaviour : EmptyNetworkBehaviour - { - - } - - internal class EmptyNetworkBehaviour : NetworkBehaviour - { - - } - } -} diff --git a/Tests/Editor/NetworkBehaviourTests.cs.meta b/Tests/Editor/NetworkBehaviourTests.cs.meta deleted file mode 100644 index 7c741c7..0000000 --- a/Tests/Editor/NetworkBehaviourTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 73e18571452c102e4b209671741f3b51 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/NetworkManagerConfigurationTests.cs b/Tests/Editor/NetworkManagerConfigurationTests.cs deleted file mode 100644 index 78b13e3..0000000 --- a/Tests/Editor/NetworkManagerConfigurationTests.cs +++ /dev/null @@ -1,563 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.Editor; -using Unity.Netcode.Transports.UTP; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace Unity.Netcode.EditorTests -{ - internal class NetworkManagerConfigurationTests - { - [SetUp] - public void OnSetup() - { - ILPPMessageProvider.IntegrationTestNoMessages = true; - } - - [TearDown] - public void OnTearDown() - { - ILPPMessageProvider.IntegrationTestNoMessages = false; - } - - /// - /// Does a simple check to make sure the nested network manager will - /// notify the user when in the editor. This is just a unit test to - /// validate this is functioning - /// - [Test] - public void NestedNetworkManagerCheck() - { - var parent = new GameObject("ParentObject"); - var networkManagerObject = new GameObject(nameof(NestedNetworkManagerCheck)); - var networkManager = networkManagerObject.AddComponent(); - - // Make our NetworkManager's GameObject nested - networkManagerObject.transform.parent = parent.transform; - - // Pre-generate the error message we are expecting to see - var messageToCheck = NetworkManager.GenerateNestedNetworkManagerMessage(networkManagerObject.transform); - - // Trap for the nested NetworkManager exception - LogAssert.Expect(LogType.Error, messageToCheck); - - // Since this is an in-editor test, we must force this invocation - NetworkManagerHelper.Singleton.NotifyUserOfNestedNetworkManager(networkManager, false, true); - - // Clean up - Object.DestroyImmediate(parent); - } - - public enum NetworkObjectPlacement - { - Root, // Added to the same root GameObject - Child // Added to a child GameObject - } - - [Test] - public void NetworkObjectNotAllowed([Values] NetworkObjectPlacement networkObjectPlacement) - { - var gameObject = new GameObject(nameof(NetworkManager)); - var targetforNetworkObject = gameObject; - - if (networkObjectPlacement == NetworkObjectPlacement.Child) - { - var childGameObject = new GameObject($"{nameof(NetworkManager)}-Child"); - childGameObject.transform.parent = targetforNetworkObject.transform; - targetforNetworkObject = childGameObject; - } - - var networkManager = gameObject.AddComponent(); - - // Trap for the error message generated when a NetworkObject is discovered on the same GameObject or any children under it - LogAssert.Expect(LogType.Error, NetworkManagerHelper.Singleton.NetworkManagerAndNetworkObjectNotAllowedMessage()); - - // Add the NetworkObject - var networkObject = targetforNetworkObject.AddComponent(); - - // Since this is an in-editor test, we must force this invocation - NetworkManagerHelper.Singleton.CheckAndNotifyUserNetworkObjectRemoved(networkManager, true); - - // Validate that the NetworkObject has been removed - if (networkObjectPlacement == NetworkObjectPlacement.Root) - { - Assert.IsNull(networkManager.gameObject.GetComponent(), $"There is still a {nameof(NetworkObject)} on {nameof(NetworkManager)}'s GameObject!"); - } - else - { - Assert.IsNull(networkManager.gameObject.GetComponentInChildren(), $"There is still a {nameof(NetworkObject)} on {nameof(NetworkManager)}'s child GameObject!"); - } - - // Clean up - Object.DestroyImmediate(gameObject); - } - - [Test] - public void NestedNetworkObjectPrefabCheck() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig(); - - var parent = new GameObject("Parent").AddComponent(); - var child = new GameObject("Child").AddComponent(); - - // Set parent - child.transform.SetParent(parent.transform); - - // Make it a prefab, warning only applies to prefabs - networkManager.AddNetworkPrefab(parent.gameObject); - - // Mark scene as dirty to ensure OnValidate actually runs - EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene()); - - // Force OnValidate - networkManager.OnValidate(); - - // Expect a warning - LogAssert.Expect(LogType.Warning, $"[Netcode] {NetworkPrefabHandler.PrefabDebugHelper(networkManager.NetworkConfig.Prefabs.Prefabs[0])} has child {nameof(NetworkObject)}(s) but they will not be spawned across the network (unsupported {nameof(NetworkPrefab)} setup)"); - - // Clean up - Object.DestroyImmediate(networkManagerObject); - Object.DestroyImmediate(parent); - - } - - [Test] - public void WhenNetworkConfigContainsOldPrefabList_TheyMigrateProperlyToTheNewList() - { - var networkConfig = new NetworkConfig(); - - var regularPrefab = new GameObject("Regular Prefab").AddComponent(); - var overriddenPrefab = new GameObject("Overridden Prefab").AddComponent(); - var overridingTargetPrefab = new GameObject("Overriding Target Prefab").AddComponent(); - var sourcePrefabToOverride = new GameObject("Overriding Source Prefab").AddComponent(); - - regularPrefab.GlobalObjectIdHash = 1; - overriddenPrefab.GlobalObjectIdHash = 2; - overridingTargetPrefab.GlobalObjectIdHash = 3; - sourcePrefabToOverride.GlobalObjectIdHash = 4; - - networkConfig.OldPrefabList = new List - { - new NetworkPrefab { Prefab = regularPrefab.gameObject }, - new NetworkPrefab { Prefab = overriddenPrefab.gameObject, Override = NetworkPrefabOverride.Prefab, OverridingTargetPrefab = overridingTargetPrefab.gameObject, SourcePrefabToOverride = sourcePrefabToOverride.gameObject, SourceHashToOverride = 123456 } - }; - - networkConfig.InitializePrefabs(); - - Assert.IsNull(networkConfig.OldPrefabList); - Assert.IsNotNull(networkConfig.Prefabs); - Assert.IsNotNull(networkConfig.Prefabs.Prefabs); - Assert.AreEqual(2, networkConfig.Prefabs.Prefabs.Count); - - Assert.AreSame(regularPrefab.gameObject, networkConfig.Prefabs.Prefabs[0].Prefab); - Assert.AreEqual(NetworkPrefabOverride.None, networkConfig.Prefabs.Prefabs[0].Override); - Assert.IsNull(networkConfig.Prefabs.Prefabs[0].SourcePrefabToOverride); - Assert.IsNull(networkConfig.Prefabs.Prefabs[0].OverridingTargetPrefab); - - Assert.AreSame(overriddenPrefab.gameObject, networkConfig.Prefabs.Prefabs[1].Prefab); - Assert.AreEqual(NetworkPrefabOverride.Prefab, networkConfig.Prefabs.Prefabs[1].Override); - Assert.AreEqual(123456, networkConfig.Prefabs.Prefabs[1].SourceHashToOverride); - Assert.AreSame(sourcePrefabToOverride.gameObject, networkConfig.Prefabs.Prefabs[1].SourcePrefabToOverride); - Assert.AreSame(overridingTargetPrefab.gameObject, networkConfig.Prefabs.Prefabs[1].OverridingTargetPrefab); - } - - [Test] - public void WhenModifyingPrefabListUsingNetworkManagerAPI_ModificationIsLocal() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - networkManager.AddNetworkPrefab(object2.gameObject); - networkManager2.AddNetworkPrefab(object3.gameObject); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsFalse(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsFalse(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsFalse(sharedList.Contains(object2.gameObject)); - Assert.IsFalse(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - - [Test] - public void WhenModifyingPrefabListUsingPrefabsAPI_ModificationIsLocal() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - networkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object2.gameObject }); - networkManager2.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object3.gameObject }); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsFalse(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsFalse(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsFalse(sharedList.Contains(object2.gameObject)); - Assert.IsFalse(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - - [Test] - public void WhenModifyingPrefabListUsingPrefabsListAPI_ModificationIsShared() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists[0].Add(new NetworkPrefab { Prefab = object2.gameObject }); - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists[0].Add(new NetworkPrefab { Prefab = object3.gameObject }); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsTrue(sharedList.Contains(object2.gameObject)); - Assert.IsTrue(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - - [Test] - public void WhenCallingInitializeAfterAddingAPrefabUsingPrefabsAPI_ThePrefabStillExists() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object2.gameObject }); - networkManager2.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object3.gameObject }); - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsFalse(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsFalse(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsFalse(sharedList.Contains(object2.gameObject)); - Assert.IsFalse(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - - [Test] - public void WhenShuttingDownAndReinitializingPrefabs_RuntimeAddedPrefabsStillExists() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - networkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object2.gameObject }); - networkManager2.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object3.gameObject }); - - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsFalse(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsFalse(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsFalse(sharedList.Contains(object2.gameObject)); - Assert.IsFalse(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - - [Test] - public void WhenCallingInitializeMultipleTimes_NothingBreaks() - { - // Setup - var networkManagerObject = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - var networkManagerObject2 = new GameObject(nameof(NestedNetworkObjectPrefabCheck)); - var networkManager2 = networkManagerObject2.AddComponent(); - networkManager2.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; - - try - { - var object1 = new GameObject("Object 1").AddComponent(); - var object2 = new GameObject("Object 2").AddComponent(); - var object3 = new GameObject("Object 3").AddComponent(); - - object1.GlobalObjectIdHash = 1; - object2.GlobalObjectIdHash = 2; - object3.GlobalObjectIdHash = 3; - - var sharedList = ScriptableObject.CreateInstance(); - sharedList.List.Add(new NetworkPrefab { Prefab = object1.gameObject }); - - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - networkManager2.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { sharedList }; - - networkManager.Initialize(true); - networkManager2.Initialize(false); - - networkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object2.gameObject }); - networkManager2.NetworkConfig.Prefabs.Add(new NetworkPrefab { Prefab = object3.gameObject }); - - networkManager.NetworkConfig.Prefabs.Initialize(); - networkManager2.NetworkConfig.Prefabs.Initialize(); - - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object1.gameObject)); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsFalse(networkManager2.NetworkConfig.Prefabs.Contains(object2.gameObject)); - Assert.IsTrue(networkManager2.NetworkConfig.Prefabs.Contains(object3.gameObject)); - Assert.IsFalse(networkManager.NetworkConfig.Prefabs.Contains(object3.gameObject)); - - Assert.IsTrue(sharedList.Contains(object1.gameObject)); - Assert.IsFalse(sharedList.Contains(object2.gameObject)); - Assert.IsFalse(sharedList.Contains(object3.gameObject)); - } - finally - { - networkManager.ShutdownInternal(); - networkManager2.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - networkManager2.NetworkConfig?.NetworkTransport.Shutdown(); - } - } - } -} diff --git a/Tests/Editor/NetworkManagerConfigurationTests.cs.meta b/Tests/Editor/NetworkManagerConfigurationTests.cs.meta deleted file mode 100644 index 5929d99..0000000 --- a/Tests/Editor/NetworkManagerConfigurationTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9b84044fccbd3cd49908f0efd5719347 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/NetworkObjectTests.cs b/Tests/Editor/NetworkObjectTests.cs deleted file mode 100644 index 64dbc53..0000000 --- a/Tests/Editor/NetworkObjectTests.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System.Text.RegularExpressions; -using NUnit.Framework; -using Unity.Netcode.Editor; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.EditorTests -{ - internal class NetworkObjectTests - { - [Test] - public void NetworkManagerOverrideTest() - { - // Create "bait" - var singletonNetworkManager = new GameObject(nameof(NetworkManager)).AddComponent(); - singletonNetworkManager.SetSingleton(); - - // Create override - var networkManager = new GameObject(nameof(NetworkManager)).AddComponent(); - - // NetworkObject - var gameObject = new GameObject(nameof(NetworkManagerOverrideTest)); - var networkObject = gameObject.AddComponent(); - - // Set override - networkObject.NetworkManagerOwner = networkManager; - - Debug.Assert(networkObject.NetworkManager == networkManager); - - Object.DestroyImmediate(singletonNetworkManager.gameObject); - Object.DestroyImmediate(networkManager.gameObject); - Object.DestroyImmediate(gameObject); - } - - [Test] - [TestCase(0)] - [TestCase(1)] - [TestCase(2)] - public void GetBehaviourIndexNone(int index) - { - var gameObject = new GameObject(nameof(GetBehaviourIndexNone)); - var networkObject = gameObject.AddComponent(); - - LogAssert.Expect(LogType.Error, new Regex(".*out of bounds.*")); - - Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex((ushort)index), Is.Null); - - // Cleanup - Object.DestroyImmediate(gameObject); - } - - [Test] - public void GetBehaviourIndexOne() - { - var gameObject = new GameObject(nameof(GetBehaviourIndexOne)); - var networkObject = gameObject.AddComponent(); - var networkBehaviour = gameObject.AddComponent(); - - LogAssert.Expect(LogType.Error, new Regex(".*out of bounds.*")); - - Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(0), Is.EqualTo(networkBehaviour)); - Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(1), Is.Null); - - // Cleanup - Object.DestroyImmediate(gameObject); - } - - /// - /// Verifies that a NetworkObject component that is positioned after a NetworkBehaviour component will - /// be migrated to a component index value that is before the lowest NetworkBehaviour component index value. - /// (The lowest NetworkBehaviour component's index value will also change when this happens) - /// - [Test] - public void NetworkObjectComponentOrder() - { - var gameObject = new GameObject(nameof(GetBehaviourIndexOne)); - // Add the Networkbehaviour first - var networkBehaviour = gameObject.AddComponent(); - // Add an empty MonoBehaviour inbetween the NetworkBehaviour and NetworkObject - gameObject.AddComponent(); - // Add the NetworkObject - var networkObject = gameObject.AddComponent(); - var componentIndices = GetIndices(gameObject); - - // Verify the NetworkObject procedes the NetworkBehaviour - Assert.True(componentIndices.NetworkObjectIndex > componentIndices.NetworkBehaviourIndex, $"[Initial Setup] NetworkObject index ({componentIndices.NetworkObjectIndex}) is not greater than the NetworkBehaviour index ({componentIndices.NetworkBehaviourIndex})!"); - - // Force-Invoke the CheckForNetworkObject method in order to verify the NetworkObject is moved - NetworkBehaviourEditor.CheckForNetworkObject(gameObject); - var adjustedIndices = GetIndices(gameObject); - - Assert.True(ValidateComponentIndices(componentIndices, GetIndices(gameObject)), "NetworkObject did not get migrated below the NetworkBehaviour!"); - - // Cleanup - Object.DestroyImmediate(gameObject); - } - - private bool ValidateComponentIndices(ComponentIndices previous, ComponentIndices current) - { - if (previous.NetworkObjectIndex != current.NetworkObjectIndex && previous.NetworkBehaviourIndex != current.NetworkBehaviourIndex) - { - if (current.NetworkObjectIndex < previous.NetworkObjectIndex && current.NetworkObjectIndex < current.NetworkBehaviourIndex) - { - return true; - } - } - return false; - } - - private ComponentIndices GetIndices(GameObject gameObject) - { - // Get the index/order values for the added NetworkBehaviour and NetworkObject - var components = gameObject.GetComponents(); - var componentIndices = new ComponentIndices() - { - NetworkObjectIndex = -1, - NetworkBehaviourIndex = -1 - }; - for (int i = 0; i < components.Length; i++) - { - if (componentIndices.NetworkObjectIndex != -1 && componentIndices.NetworkBehaviourIndex != -1) - { - break; - } - var component = components[i]; - var networkObjectComponent = component as NetworkObject; - if (networkObjectComponent != null) - { - componentIndices.NetworkObjectIndex = i; - continue; - } - var networkBehaviourComponent = component as EmptyNetworkBehaviour; - if (networkBehaviourComponent != null) - { - componentIndices.NetworkBehaviourIndex = i; - continue; - } - } - - return componentIndices; - } - - private struct ComponentIndices - { - public int NetworkObjectIndex; - public int NetworkBehaviourIndex; - } - - internal class EmptyNetworkBehaviour : NetworkBehaviour - { - - } - - internal class EmptyMonoBehaviour : MonoBehaviour - { - - } - } -} diff --git a/Tests/Editor/NetworkObjectTests.cs.meta b/Tests/Editor/NetworkObjectTests.cs.meta deleted file mode 100644 index 70ddc85..0000000 --- a/Tests/Editor/NetworkObjectTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 542af4c12ffee14f59967bc8e41f5e9d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/NetworkPrefabProcessorTests.cs b/Tests/Editor/NetworkPrefabProcessorTests.cs deleted file mode 100644 index f50e502..0000000 --- a/Tests/Editor/NetworkPrefabProcessorTests.cs +++ /dev/null @@ -1,90 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.Editor.Configuration; -using UnityEditor; -using UnityEngine; - -namespace Unity.Netcode.EditorTests -{ - internal class NetworkPrefabProcessorTests - { - private NetcodeForGameObjectsProjectSettings m_Settings; - private bool m_EditorDefaultPrefabSetting; - private string m_EditorDefaultPrefabLocation; - - private GameObject m_Prefab; - - private const string k_PrefabName = "Assets/TestPrefab.prefab"; - private const string k_DefaultAssetString = "Assets/TestPrefabList.asset"; - - [SetUp] - public void SetUp() - { - m_Settings = NetcodeForGameObjectsProjectSettings.instance; - m_EditorDefaultPrefabSetting = m_Settings.GenerateDefaultNetworkPrefabs; - m_EditorDefaultPrefabLocation = NetworkPrefabProcessor.DefaultNetworkPrefabsPath; - NetworkPrefabProcessor.DefaultNetworkPrefabsPath = k_DefaultAssetString; - } - - [TearDown] - public void TearDown() - { - m_Settings.GenerateDefaultNetworkPrefabs = m_EditorDefaultPrefabSetting; - NetworkPrefabProcessor.DefaultNetworkPrefabsPath = m_EditorDefaultPrefabLocation; - AssetDatabase.DeleteAsset(k_PrefabName); - AssetDatabase.DeleteAsset(k_DefaultAssetString); - } - - [Test] - public void WhenGenerateDefaultNetworkPrefabsIsEnabled_AddingAPrefabUpdatesDefaultPrefabList() - { - var obj = new GameObject("Object"); - obj.AddComponent(); - m_Settings.GenerateDefaultNetworkPrefabs = true; - m_Prefab = PrefabUtility.SaveAsPrefabAsset(obj, k_PrefabName); - Object.DestroyImmediate(obj); - - var prefabList = NetworkPrefabProcessor.GetOrCreateNetworkPrefabs(NetworkPrefabProcessor.DefaultNetworkPrefabsPath, out var isNew, false); - Assert.IsFalse(isNew); - Assert.IsTrue(prefabList.Contains(m_Prefab)); - } - - [Test] - public void WhenGenerateDefaultNetworkPrefabsIsEnabled_RemovingAPrefabUpdatesDefaultPrefabList() - { - WhenGenerateDefaultNetworkPrefabsIsEnabled_AddingAPrefabUpdatesDefaultPrefabList(); - - AssetDatabase.DeleteAsset(k_PrefabName); - var prefabList = NetworkPrefabProcessor.GetOrCreateNetworkPrefabs(NetworkPrefabProcessor.DefaultNetworkPrefabsPath, out var isNew, false); - Assert.IsFalse(isNew); - Assert.IsFalse(prefabList.Contains(m_Prefab)); - } - - [Test] - public void WhenGenerateDefaultNetworkPrefabsIsNotEnabled_AddingAPrefabDoesNotUpdateDefaultPrefabList() - { - var obj = new GameObject("Object"); - obj.AddComponent(); - m_Settings.GenerateDefaultNetworkPrefabs = false; - m_Prefab = PrefabUtility.SaveAsPrefabAsset(obj, k_PrefabName); - Object.DestroyImmediate(obj); - - var prefabList = NetworkPrefabProcessor.GetOrCreateNetworkPrefabs(NetworkPrefabProcessor.DefaultNetworkPrefabsPath, out var isNew, false); - Assert.IsTrue(isNew); - Assert.IsFalse(prefabList.Contains(m_Prefab)); - } - - [Test] - public void WhenGenerateDefaultNetworkPrefabsIsNotEnabled_RemovingAPrefabDoesNotUpdateDefaultPrefabList() - { - // Add it with the list enabled, then disable the list. Removing it - // should then be nop. - WhenGenerateDefaultNetworkPrefabsIsEnabled_AddingAPrefabUpdatesDefaultPrefabList(); - - m_Settings.GenerateDefaultNetworkPrefabs = false; - AssetDatabase.DeleteAsset(k_PrefabName); - var prefabList = NetworkPrefabProcessor.GetOrCreateNetworkPrefabs(NetworkPrefabProcessor.DefaultNetworkPrefabsPath, out var isNew, false); - Assert.IsFalse(isNew); - Assert.IsTrue(prefabList.Contains(m_Prefab)); - } - } -} diff --git a/Tests/Editor/NetworkPrefabProcessorTests.cs.meta b/Tests/Editor/NetworkPrefabProcessorTests.cs.meta deleted file mode 100644 index c95423a..0000000 --- a/Tests/Editor/NetworkPrefabProcessorTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 6471efe05b0548ef9d2171e07d4a561b -timeCreated: 1669140101 \ No newline at end of file diff --git a/Tests/Editor/NetworkVar.meta b/Tests/Editor/NetworkVar.meta deleted file mode 100644 index 8382298..0000000 --- a/Tests/Editor/NetworkVar.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ed3be13d96c34bc4b8676ce550cee041 -timeCreated: 1647861659 \ No newline at end of file diff --git a/Tests/Editor/NetworkVar/NetworkVarTests.cs b/Tests/Editor/NetworkVar/NetworkVarTests.cs deleted file mode 100644 index 77ad69d..0000000 --- a/Tests/Editor/NetworkVar/NetworkVarTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.EditorTests.NetworkVar -{ - internal class NetworkVarTests - { - internal class NetworkVarComponent : NetworkBehaviour - { - public NetworkVariable NetworkVariable = new NetworkVariable(); - } - [Test] - public void TestAssignmentUnchanged() - { - var gameObjectMan = new GameObject(); - var networkManager = gameObjectMan.AddComponent(); - networkManager.BehaviourUpdater = new NetworkBehaviourUpdater(); - var gameObject = new GameObject(); - var networkObject = gameObject.AddComponent(); - networkObject.NetworkManagerOwner = networkManager; - var networkVarComponent = gameObject.AddComponent(); - networkVarComponent.NetworkVariable.Initialize(networkVarComponent); - networkVarComponent.NetworkVariable.Value = 314159265; - networkVarComponent.NetworkVariable.OnValueChanged += (value, newValue) => - { - Assert.Fail("OnValueChanged was invoked when setting the same value"); - }; - networkVarComponent.NetworkVariable.Value = 314159265; - Object.DestroyImmediate(gameObject); - Object.DestroyImmediate(gameObjectMan); - } - [Test] - public void TestAssignmentChanged() - { - var gameObjectMan = new GameObject(); - var networkManager = gameObjectMan.AddComponent(); - networkManager.BehaviourUpdater = new NetworkBehaviourUpdater(); - var gameObject = new GameObject(); - var networkObject = gameObject.AddComponent(); - var networkVarComponent = gameObject.AddComponent(); - networkObject.NetworkManagerOwner = networkManager; - networkVarComponent.NetworkVariable.Initialize(networkVarComponent); - networkVarComponent.NetworkVariable.Value = 314159265; - var changed = false; - networkVarComponent.NetworkVariable.OnValueChanged += (value, newValue) => - { - changed = true; - }; - networkVarComponent.NetworkVariable.Value = 314159266; - Assert.True(changed); - Object.DestroyImmediate(gameObject); - Object.DestroyImmediate(gameObjectMan); - } - } -} diff --git a/Tests/Editor/NetworkVar/NetworkVarTests.cs.meta b/Tests/Editor/NetworkVar/NetworkVarTests.cs.meta deleted file mode 100644 index a282884..0000000 --- a/Tests/Editor/NetworkVar/NetworkVarTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a7cdd8c1251f4352b1f1d4825dc85182 -timeCreated: 1647861669 \ No newline at end of file diff --git a/Tests/Editor/Serialization.meta b/Tests/Editor/Serialization.meta deleted file mode 100644 index 8a7aaf9..0000000 --- a/Tests/Editor/Serialization.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e12c4be6e89f459aa2826abba8c8d301 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs b/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs deleted file mode 100644 index 53e72cf..0000000 --- a/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs +++ /dev/null @@ -1,1304 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal abstract class BaseFastBufferReaderWriterTest - { - protected enum ByteEnum : byte - { - A, - B, - C = byte.MaxValue - } - protected enum SByteEnum : sbyte - { - A, - B, - C = sbyte.MaxValue - } - protected enum ShortEnum : short - { - A, - B, - C = short.MaxValue - } - protected enum UShortEnum : ushort - { - A, - B, - C = ushort.MaxValue - } - protected enum IntEnum : int - { - A, - B, - C = int.MaxValue - } - protected enum UIntEnum : uint - { - A, - B, - C = uint.MaxValue - } - protected enum LongEnum : long - { - A, - B, - C = long.MaxValue - } - protected enum ULongEnum : ulong - { - A, - B, - C = ulong.MaxValue - } - - protected struct TestStruct : INetworkSerializeByMemcpy - { - public byte A; - public short B; - public ushort C; - public int D; - public uint E; - public long F; - public ulong G; - public bool H; - public char I; - public float J; - public double K; - } - - public enum WriteType - { - WriteDirect, - WriteSafe - } - - protected abstract void RunTypeTest(T valueToTest) where T : unmanaged; - - protected abstract void RunTypeTestSafe(T valueToTest) where T : unmanaged; - - protected abstract void RunTypeArrayTest(T[] valueToTest) where T : unmanaged; - - protected abstract void RunTypeArrayTestSafe(T[] valueToTest) where T : unmanaged; - - protected abstract void RunTypeNativeArrayTest(NativeArray valueToTest) where T : unmanaged; - - protected abstract void RunTypeNativeArrayTestSafe(NativeArray valueToTest) where T : unmanaged; - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - protected abstract void RunTypeNativeListTest(NativeList valueToTest) where T : unmanaged; - - protected abstract void RunTypeNativeListTestSafe(NativeList valueToTest) where T : unmanaged; -#endif - - private Random m_Random = new Random(); - protected TestStruct GetTestStruct() - { - var testStruct = new TestStruct - { - A = (byte)m_Random.Next(), - B = (short)m_Random.Next(), - C = (ushort)m_Random.Next(), - D = m_Random.Next(), - E = (uint)m_Random.Next(), - F = ((long)m_Random.Next() << 32) + m_Random.Next(), - G = ((ulong)m_Random.Next() << 32) + (ulong)m_Random.Next(), - H = true, - I = '\u263a', - J = (float)m_Random.NextDouble(), - K = m_Random.NextDouble(), - }; - - return testStruct; - } - - private void RunTestWithWriteType(T val, WriteType wt, FastBufferWriter.ForPrimitives _ = default) where T : unmanaged - { - switch (wt) - { - case WriteType.WriteDirect: - RunTypeTest(val); - break; - case WriteType.WriteSafe: - RunTypeTestSafe(val); - break; - } - } - - public void BaseTypeTest(Type testType, WriteType writeType) - { - var random = new Random(); - - if (testType == typeof(byte)) - { - RunTestWithWriteType((byte)random.Next(), writeType); - } - else if (testType == typeof(sbyte)) - { - RunTestWithWriteType((sbyte)random.Next(), writeType); - } - else if (testType == typeof(short)) - { - RunTestWithWriteType((short)random.Next(), writeType); - } - else if (testType == typeof(ushort)) - { - RunTestWithWriteType((ushort)random.Next(), writeType); - } - else if (testType == typeof(int)) - { - RunTestWithWriteType(random.Next(), writeType); - } - else if (testType == typeof(uint)) - { - RunTestWithWriteType((uint)random.Next(), writeType); - } - else if (testType == typeof(long)) - { - RunTestWithWriteType(((long)random.Next() << 32) + random.Next(), writeType); - } - else if (testType == typeof(ulong)) - { - RunTestWithWriteType(((ulong)random.Next() << 32) + (ulong)random.Next(), writeType); - } - else if (testType == typeof(bool)) - { - RunTestWithWriteType(true, writeType); - } - else if (testType == typeof(char)) - { - RunTestWithWriteType('a', writeType); - RunTestWithWriteType('\u263a', writeType); - } - else if (testType == typeof(float)) - { - RunTestWithWriteType((float)random.NextDouble(), writeType); - } - else if (testType == typeof(double)) - { - RunTestWithWriteType(random.NextDouble(), writeType); - } - else if (testType == typeof(ByteEnum)) - { - RunTestWithWriteType(ByteEnum.C, writeType); - } - else if (testType == typeof(SByteEnum)) - { - RunTestWithWriteType(SByteEnum.C, writeType); - } - else if (testType == typeof(ShortEnum)) - { - RunTestWithWriteType(ShortEnum.C, writeType); - } - else if (testType == typeof(UShortEnum)) - { - RunTestWithWriteType(UShortEnum.C, writeType); - } - else if (testType == typeof(IntEnum)) - { - RunTestWithWriteType(IntEnum.C, writeType); - } - else if (testType == typeof(UIntEnum)) - { - RunTestWithWriteType(UIntEnum.C, writeType); - } - else if (testType == typeof(LongEnum)) - { - RunTestWithWriteType(LongEnum.C, writeType); - } - else if (testType == typeof(ULongEnum)) - { - RunTestWithWriteType(ULongEnum.C, writeType); - } - else if (testType == typeof(Vector2)) - { - RunTestWithWriteType(new Vector2((float)random.NextDouble(), (float)random.NextDouble()), writeType); - } - else if (testType == typeof(Vector3)) - { - RunTestWithWriteType(new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), writeType); - } - else if (testType == typeof(Vector2Int)) - { - RunTestWithWriteType(new Vector2Int((int)random.NextDouble(), (int)random.NextDouble()), writeType); - } - else if (testType == typeof(Vector3Int)) - { - RunTestWithWriteType(new Vector3Int((int)random.NextDouble(), (int)random.NextDouble(), (int)random.NextDouble()), writeType); - } - else if (testType == typeof(Vector4)) - { - RunTestWithWriteType(new Vector4((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), writeType); - } - else if (testType == typeof(Quaternion)) - { - RunTestWithWriteType(new Quaternion((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), writeType); - } - else if (testType == typeof(Color)) - { - RunTestWithWriteType(new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), writeType); - } - else if (testType == typeof(Color32)) - { - RunTestWithWriteType(new Color32((byte)random.Next(), (byte)random.Next(), (byte)random.Next(), (byte)random.Next()), writeType); - } - else if (testType == typeof(Ray)) - { - RunTestWithWriteType(new Ray( - new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), - new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble())), writeType); - } - else if (testType == typeof(Ray2D)) - { - RunTestWithWriteType(new Ray2D( - new Vector2((float)random.NextDouble(), (float)random.NextDouble()), - new Vector2((float)random.NextDouble(), (float)random.NextDouble())), writeType); - } - else if (testType == typeof(TestStruct)) - { - RunTestWithWriteType(GetTestStruct(), writeType); - } - else - { - Assert.Fail("No type handler was provided for this type in the test!"); - } - } - - public void BaseArrayTypeTest(Type testType, WriteType writeType) - { - var random = new Random(); - void RunTypeTestLocal(T[] val, WriteType wt) where T : unmanaged - { - switch (wt) - { - case WriteType.WriteDirect: - RunTypeArrayTest(val); - break; - case WriteType.WriteSafe: - RunTypeArrayTestSafe(val); - break; - } - } - - if (testType == typeof(byte)) - { - RunTypeTestLocal(new[]{ - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next() - }, writeType); - } - else if (testType == typeof(sbyte)) - { - RunTypeTestLocal(new[]{ - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next() - }, writeType); - } - else if (testType == typeof(short)) - { - RunTypeTestLocal(new[]{ - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next() - }, writeType); - } - else if (testType == typeof(ushort)) - { - RunTypeTestLocal(new[]{ - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next() - }, writeType); - } - else if (testType == typeof(int)) - { - RunTypeTestLocal(new[]{ - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next() - }, writeType); - } - else if (testType == typeof(uint)) - { - RunTypeTestLocal(new[]{ - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next() - }, writeType); - } - else if (testType == typeof(long)) - { - RunTypeTestLocal(new[]{ - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next() - }, writeType); - } - else if (testType == typeof(ulong)) - { - RunTypeTestLocal(new[]{ - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next() - }, writeType); - } - else if (testType == typeof(bool)) - { - RunTypeTestLocal(new[]{ - true, - false, - true, - true, - false, - false, - true, - false, - true - }, writeType); - } - else if (testType == typeof(char)) - { - RunTypeTestLocal(new[]{ - 'a', - '\u263a' - }, writeType); - } - else if (testType == typeof(float)) - { - RunTypeTestLocal(new[]{ - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble() - }, writeType); - } - else if (testType == typeof(double)) - { - RunTypeTestLocal(new[]{ - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble() - }, writeType); - } - else if (testType == typeof(ByteEnum)) - { - RunTypeTestLocal(new[]{ - ByteEnum.C, - ByteEnum.A, - ByteEnum.B - }, writeType); - } - else if (testType == typeof(SByteEnum)) - { - RunTypeTestLocal(new[]{ - SByteEnum.C, - SByteEnum.A, - SByteEnum.B - }, writeType); - } - else if (testType == typeof(ShortEnum)) - { - RunTypeTestLocal(new[]{ - ShortEnum.C, - ShortEnum.A, - ShortEnum.B - }, writeType); - } - else if (testType == typeof(UShortEnum)) - { - RunTypeTestLocal(new[]{ - UShortEnum.C, - UShortEnum.A, - UShortEnum.B - }, writeType); - } - else if (testType == typeof(IntEnum)) - { - RunTypeTestLocal(new[]{ - IntEnum.C, - IntEnum.A, - IntEnum.B - }, writeType); - } - else if (testType == typeof(UIntEnum)) - { - RunTypeTestLocal(new[]{ - UIntEnum.C, - UIntEnum.A, - UIntEnum.B - }, writeType); - } - else if (testType == typeof(LongEnum)) - { - RunTypeTestLocal(new[]{ - LongEnum.C, - LongEnum.A, - LongEnum.B - }, writeType); - } - else if (testType == typeof(ULongEnum)) - { - RunTypeTestLocal(new[]{ - ULongEnum.C, - ULongEnum.A, - ULongEnum.B - }, writeType); - } - else if (testType == typeof(Vector2)) - { - RunTypeTestLocal(new[]{ - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Vector3)) - { - RunTypeTestLocal(new[]{ - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Vector2Int)) - { - RunTypeTestLocal(new[]{ - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Vector3Int)) - { - RunTypeTestLocal(new[]{ - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Vector4)) - { - RunTypeTestLocal(new[]{ - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Quaternion)) - { - RunTypeTestLocal(new[]{ - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Color)) - { - RunTypeTestLocal(new[]{ - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, writeType); - } - else if (testType == typeof(Color32)) - { - RunTypeTestLocal(new[]{ - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - }, writeType); - } - else if (testType == typeof(Ray)) - { - RunTypeTestLocal(new[]{ - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - }, writeType); - } - else if (testType == typeof(Ray2D)) - { - RunTypeTestLocal(new[]{ - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - }, writeType); - } - else if (testType == typeof(TestStruct)) - { - RunTypeTestLocal(new[] { - GetTestStruct(), - GetTestStruct(), - GetTestStruct(), - }, writeType); - } - else - { - Assert.Fail("No type handler was provided for this type in the test!"); - } - } - - public void BaseNativeArrayTypeTest(Type testType, WriteType writeType) - { - var random = new Random(); - void RunTypeTestLocal(NativeArray val, WriteType wt) where T : unmanaged - { - switch (wt) - { - case WriteType.WriteDirect: - RunTypeNativeArrayTest(val); - break; - case WriteType.WriteSafe: - RunTypeNativeArrayTestSafe(val); - break; - } - } - - if (testType == typeof(byte)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(sbyte)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(short)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ushort)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(uint)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(long)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ulong)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(bool)) - { - RunTypeTestLocal(new NativeArray(new[]{ - true, - false, - true, - true, - false, - false, - true, - false, - true - }, Allocator.Temp), writeType); - } - else if (testType == typeof(char)) - { - RunTypeTestLocal(new NativeArray(new[]{ - 'a', - '\u263a' - }, Allocator.Temp), writeType); - } - else if (testType == typeof(float)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(double)) - { - RunTypeTestLocal(new NativeArray(new[]{ - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ByteEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ByteEnum.C, - ByteEnum.A, - ByteEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(SByteEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - SByteEnum.C, - SByteEnum.A, - SByteEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ShortEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ShortEnum.C, - ShortEnum.A, - ShortEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(UShortEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - UShortEnum.C, - UShortEnum.A, - UShortEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(IntEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - IntEnum.C, - IntEnum.A, - IntEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(UIntEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - UIntEnum.C, - UIntEnum.A, - UIntEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(LongEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - LongEnum.C, - LongEnum.A, - LongEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ULongEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ULongEnum.C, - ULongEnum.A, - ULongEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector2)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector3)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector2Int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector3Int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector4)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Quaternion)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Color)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Color32)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Ray)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Ray2D)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(TestStruct)) - { - RunTypeTestLocal(new NativeArray(new[] { - GetTestStruct(), - GetTestStruct(), - GetTestStruct(), - }, Allocator.Temp), writeType); - } - else - { - Assert.Fail("No type handler was provided for this type in the test!"); - } - } -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public void BaseNativeListTypeTest(Type testType, WriteType writeType) - { - var random = new Random(); - void RunTypeTestLocal(NativeArray val, WriteType wt) where T : unmanaged - { - var lst = new NativeList(val.Length, Allocator.Temp); - foreach (var item in val) - { - lst.Add(item); - } - switch (wt) - { - case WriteType.WriteDirect: - RunTypeNativeListTest(lst); - break; - case WriteType.WriteSafe: - RunTypeNativeListTestSafe(lst); - break; - } - } - - if (testType == typeof(byte)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next(), - (byte) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(sbyte)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next(), - (sbyte) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(short)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next(), - (short) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ushort)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next(), - (ushort) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next(), - random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(uint)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next(), - (uint) random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(long)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next(), - ((long)random.Next() << 32) + random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ulong)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next(), - ((ulong)random.Next() << 32) + (ulong)random.Next() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(bool)) - { - RunTypeTestLocal(new NativeArray(new[]{ - true, - false, - true, - true, - false, - false, - true, - false, - true - }, Allocator.Temp), writeType); - } - else if (testType == typeof(char)) - { - RunTypeTestLocal(new NativeArray(new[]{ - 'a', - '\u263a' - }, Allocator.Temp), writeType); - } - else if (testType == typeof(float)) - { - RunTypeTestLocal(new NativeArray(new[]{ - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble(), - (float)random.NextDouble() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(double)) - { - RunTypeTestLocal(new NativeArray(new[]{ - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble(), - random.NextDouble() - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ByteEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ByteEnum.C, - ByteEnum.A, - ByteEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(SByteEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - SByteEnum.C, - SByteEnum.A, - SByteEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ShortEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ShortEnum.C, - ShortEnum.A, - ShortEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(UShortEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - UShortEnum.C, - UShortEnum.A, - UShortEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(IntEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - IntEnum.C, - IntEnum.A, - IntEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(UIntEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - UIntEnum.C, - UIntEnum.A, - UIntEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(LongEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - LongEnum.C, - LongEnum.A, - LongEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(ULongEnum)) - { - RunTypeTestLocal(new NativeArray(new[]{ - ULongEnum.C, - ULongEnum.A, - ULongEnum.B - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector2)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector3)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector2Int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - new Vector2Int((int) random.NextDouble(), (int) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector3Int)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - new Vector3Int((int) random.NextDouble(), (int) random.NextDouble(), (int) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Vector4)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector4((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Quaternion)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - new Quaternion((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble(), (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Color)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Color((float) random.NextDouble(), (float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Color32)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - new Color32((byte) random.Next(), (byte) random.Next(), (byte) random.Next(), (byte) random.Next()), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Ray)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - new Ray( - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble()), - new Vector3((float) random.NextDouble(), (float) random.NextDouble(), - (float) random.NextDouble())), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(Ray2D)) - { - RunTypeTestLocal(new NativeArray(new[]{ - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - new Ray2D( - new Vector2((float) random.NextDouble(), (float) random.NextDouble()), - new Vector2((float) random.NextDouble(), (float) random.NextDouble())), - }, Allocator.Temp), writeType); - } - else if (testType == typeof(TestStruct)) - { - RunTypeTestLocal(new NativeArray(new[] { - GetTestStruct(), - GetTestStruct(), - GetTestStruct(), - }, Allocator.Temp), writeType); - } - else - { - Assert.Fail("No type handler was provided for this type in the test!"); - } - } -#endif - } -} diff --git a/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs.meta b/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs.meta deleted file mode 100644 index f0b683d..0000000 --- a/Tests/Editor/Serialization/BaseFastBufferReaderWriterTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 573b1f36caed496a9c6e0eaa788d0c29 -timeCreated: 1629917174 \ No newline at end of file diff --git a/Tests/Editor/Serialization/BitCounterTests.cs b/Tests/Editor/Serialization/BitCounterTests.cs deleted file mode 100644 index 9200d6b..0000000 --- a/Tests/Editor/Serialization/BitCounterTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class BitCounterTests - { - [Test] - public void WhenCountingUsedBitsIn64BitValue_ResultMatchesHighBitSetPlusOne([Range(0, 63)] int highBit) - { - if (highBit == 0) - { - ulong value = 0; - // 0 is a special case. All values are considered at least 1 bit. - Assert.AreEqual(1, BitCounter.GetUsedBitCount(value)); - } - else - { - ulong value = 1UL << highBit; - Assert.AreEqual(highBit + 1, BitCounter.GetUsedBitCount(value)); - } - } - - [Test] - public void WhenCountingUsedBitsIn32BitValue_ResultMatchesHighBitSetPlusOne([Range(0, 31)] int highBit) - { - if (highBit == 0) - { - uint value = 0; - // 0 is a special case. All values are considered at least 1 bit. - Assert.AreEqual(1, BitCounter.GetUsedBitCount(value)); - } - else - { - uint value = 1U << highBit; - Assert.AreEqual(highBit + 1, BitCounter.GetUsedBitCount(value)); - } - } - - [Test] - public void WhenCountingUsedBytesIn64BitValue_ResultMatchesHighBitSetOver8PlusOne([Range(0, 63)] int highBit) - { - if (highBit == 0) - { - ulong value = 0; - // 0 is a special case. All values are considered at least 1 byte. - Assert.AreEqual(1, BitCounter.GetUsedByteCount(value)); - } - else - { - ulong value = 1UL << highBit; - Assert.AreEqual(highBit / 8 + 1, BitCounter.GetUsedByteCount(value)); - } - } - - [Test] - public void WhenCountingUsedBytesIn32BitValue_ResultMatchesHighBitSetOver8PlusOne([Range(0, 31)] int highBit) - { - if (highBit == 0) - { - uint value = 0; - // 0 is a special case. All values are considered at least 1 byte. - Assert.AreEqual(1, BitCounter.GetUsedByteCount(value)); - } - else - { - uint value = 1U << highBit; - Assert.AreEqual(highBit / 8 + 1, BitCounter.GetUsedByteCount(value)); - } - } - } -} diff --git a/Tests/Editor/Serialization/BitCounterTests.cs.meta b/Tests/Editor/Serialization/BitCounterTests.cs.meta deleted file mode 100644 index 64a1375..0000000 --- a/Tests/Editor/Serialization/BitCounterTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 76e459b9c2aeea94ebf448c237061485 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/BitReaderTests.cs b/Tests/Editor/Serialization/BitReaderTests.cs deleted file mode 100644 index de83183..0000000 --- a/Tests/Editor/Serialization/BitReaderTests.cs +++ /dev/null @@ -1,371 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; - -namespace Unity.Netcode.EditorTests -{ - internal class BitReaderTests - { - [Test] - public void TestReadingOneBit() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBit(true); - - bitWriter.WriteBit(true); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(false); - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - } - - writer.WriteByte(0b11111111); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - Assert.IsTrue(reader.TryBeginRead(3)); - using (var bitReader = reader.EnterBitwiseContext()) - { - bool b; - bitReader.ReadBit(out b); - Assert.IsTrue(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - } - - reader.ReadByte(out byte lastByte); - Assert.AreEqual(0b11111111, lastByte); - } - } - } - [Test] - public unsafe void TestTryBeginReadBits() - { - var nativeArray = new NativeArray(4, Allocator.Temp); - var reader = new FastBufferReader(nativeArray, Allocator.Temp); - nativeArray.Dispose(); - using (reader) - { - int* asInt = (int*)reader.GetUnsafePtr(); - *asInt = 0b11111111_00001010_10101011; - - using (var bitReader = reader.EnterBitwiseContext()) - { - Assert.Throws(() => reader.TryBeginRead(1)); - Assert.Throws(() => reader.TryBeginReadValue(1)); - Assert.IsTrue(bitReader.TryBeginReadBits(1)); - bitReader.ReadBit(out bool b); - Assert.IsTrue(b); - - // Can't use Assert.Throws() because ref struct BitWriter can't be captured in a lambda - try - { - bitReader.ReadBit(out b); - } - catch (OverflowException) - { - // Should get called here. - } - Assert.IsTrue(bitReader.TryBeginReadBits(3)); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - bitReader.ReadBit(out b); - Assert.IsFalse(b); - bitReader.ReadBit(out b); - Assert.IsTrue(b); - - byte byteVal; - try - { - bitReader.ReadBits(out byteVal, 4); - } - catch (OverflowException) - { - // Should get called here. - } - - try - { - bitReader.ReadBits(out byteVal, 1); - } - catch (OverflowException) - { - // Should get called here. - } - Assert.IsTrue(bitReader.TryBeginReadBits(3)); - - try - { - bitReader.ReadBits(out byteVal, 4); - } - catch (OverflowException) - { - // Should get called here. - } - Assert.IsTrue(bitReader.TryBeginReadBits(4)); - bitReader.ReadBits(out byteVal, 3); - Assert.AreEqual(0b010, byteVal); - - Assert.IsTrue(bitReader.TryBeginReadBits(5)); - - bitReader.ReadBits(out byteVal, 5); - Assert.AreEqual(0b10101, byteVal); - } - - Assert.AreEqual(2, reader.Position); - - Assert.IsTrue(reader.TryBeginRead(1)); - reader.ReadByte(out byte nextByte); - Assert.AreEqual(0b11111111, nextByte); - - Assert.IsTrue(reader.TryBeginRead(1)); - reader.ReadByte(out nextByte); - Assert.AreEqual(0b00000000, nextByte); - - Assert.IsFalse(reader.TryBeginRead(1)); - using (var bitReader = reader.EnterBitwiseContext()) - { - Assert.IsFalse(bitReader.TryBeginReadBits(1)); - } - } - } - - [Test] - public void TestReadingMultipleBits() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(0b11111111, 1); - bitWriter.WriteBits(0b11111111, 1); - bitWriter.WriteBits(0b11111110, 2); - bitWriter.WriteBits(0b11111000, 4); - bitWriter.WriteBits(0b11111010, 4); - } - writer.WriteByte(0b11111111); - - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - Assert.IsTrue(reader.TryBeginRead(3)); - using (var bitReader = reader.EnterBitwiseContext()) - { - byte b; - bitReader.ReadBits(out b, 1); - Assert.AreEqual(0b1, b); - - bitReader.ReadBits(out b, 1); - Assert.AreEqual(0b1, b); - - bitReader.ReadBits(out b, 2); - Assert.AreEqual(0b10, b); - - bitReader.ReadBits(out b, 4); - Assert.AreEqual(0b1000, b); - - bitReader.ReadBits(out b, 4); - Assert.AreEqual(0b1010, b); - } - - reader.ReadByte(out byte lastByte); - Assert.AreEqual(0b11111111, lastByte); - } - } - } - - [Test] - public void TestReadingMultipleBitsToLongs() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(0b11111111UL, 1); - bitWriter.WriteBits(0b11111111UL, 1); - bitWriter.WriteBits(0b11111110UL, 2); - bitWriter.WriteBits(0b11111000UL, 4); - bitWriter.WriteBits(0b11111010UL, 4); - } - - writer.WriteByte(0b11111111); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - Assert.IsTrue(reader.TryBeginRead(3)); - using (var bitReader = reader.EnterBitwiseContext()) - { - ulong ul; - bitReader.ReadBits(out ul, 1); - Assert.AreEqual(0b1, ul); - - bitReader.ReadBits(out ul, 1); - Assert.AreEqual(0b1, ul); - - bitReader.ReadBits(out ul, 2); - Assert.AreEqual(0b10, ul); - - bitReader.ReadBits(out ul, 4); - Assert.AreEqual(0b1000, ul); - - bitReader.ReadBits(out ul, 4); - Assert.AreEqual(0b1010, ul); - } - - reader.ReadByte(out byte lastByte); - Assert.AreEqual(0b11111111, lastByte); - } - } - } - - [Test] - public unsafe void TestReadingMultipleBytesToLongs([Range(1U, 64U)] uint numBits) - { - ulong value = 0xFFFFFFFFFFFFFFFF; - var reader = new FastBufferReader((byte*)&value, Allocator.Temp, sizeof(ulong)); - using (reader) - { - ulong* asUlong = (ulong*)reader.GetUnsafePtr(); - - Assert.AreEqual(value, *asUlong); - var mask = 0UL; - for (var i = 0; i < numBits; ++i) - { - mask |= (1UL << i); - } - - ulong readValue; - - Assert.IsTrue(reader.TryBeginRead(sizeof(ulong))); - using (var bitReader = reader.EnterBitwiseContext()) - { - bitReader.ReadBits(out readValue, numBits); - } - Assert.AreEqual(value & mask, readValue); - } - } - - [Test] - public unsafe void TestReadingMultipleBytesToLongsMisaligned([Range(1U, 63U)] uint numBits) - { - ulong value = 0b01010101_10101010_01010101_10101010_01010101_10101010_01010101_10101010; - var reader = new FastBufferReader((byte*)&value, Allocator.Temp, sizeof(ulong)); - using (reader) - { - ulong* asUlong = (ulong*)reader.GetUnsafePtr(); - - Assert.AreEqual(value, *asUlong); - var mask = 0UL; - for (var i = 0; i < numBits; ++i) - { - mask |= (1UL << i); - } - - ulong readValue; - - Assert.IsTrue(reader.TryBeginRead(sizeof(ulong))); - using (var bitReader = reader.EnterBitwiseContext()) - { - bitReader.ReadBit(out bool unused); - bitReader.ReadBits(out readValue, numBits); - } - Assert.AreEqual((value >> 1) & mask, readValue); - } - } - - [Test] - public unsafe void TestReadingBitsThrowsIfTryBeginReadNotCalled() - { - var nativeArray = new NativeArray(4, Allocator.Temp); - var reader = new FastBufferReader(nativeArray, Allocator.Temp); - nativeArray.Dispose(); - using (reader) - { - int* asInt = (int*)reader.GetUnsafePtr(); - *asInt = 0b11111111_00001010_10101011; - - Assert.Throws(() => - { - using var bitReader = reader.EnterBitwiseContext(); - bitReader.ReadBit(out bool b); - }); - - Assert.Throws(() => - { - using var bitReader = reader.EnterBitwiseContext(); - bitReader.ReadBits(out byte b, 1); - }); - - Assert.Throws(() => - { - using var bitReader = reader.EnterBitwiseContext(); - bitReader.ReadBits(out ulong ul, 1); - }); - - Assert.AreEqual(0, reader.Position); - - Assert.Throws(() => - { - Assert.IsTrue(reader.TryBeginRead(1)); - using var bitReader = reader.EnterBitwiseContext(); - ulong ul; - try - { - bitReader.ReadBits(out ul, 4); - bitReader.ReadBits(out ul, 4); - } - catch (OverflowException) - { - Assert.Fail("Overflow exception was thrown too early."); - throw; - } - bitReader.ReadBits(out ul, 4); - }); - - } - } - } -} diff --git a/Tests/Editor/Serialization/BitReaderTests.cs.meta b/Tests/Editor/Serialization/BitReaderTests.cs.meta deleted file mode 100644 index 0dc0f36..0000000 --- a/Tests/Editor/Serialization/BitReaderTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 67df11865abcd5843a4e142cf6bbd901 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/BitWriterTests.cs b/Tests/Editor/Serialization/BitWriterTests.cs deleted file mode 100644 index b4a84ff..0000000 --- a/Tests/Editor/Serialization/BitWriterTests.cs +++ /dev/null @@ -1,333 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; - -namespace Unity.Netcode.EditorTests -{ - internal class BitWriterTests - { - [Test] - public unsafe void TestWritingOneBit() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - int* asInt = (int*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asInt); - - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBit(true); - Assert.AreEqual(0b1, *asInt); - - bitWriter.WriteBit(true); - Assert.AreEqual(0b11, *asInt); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - Assert.AreEqual(0b1011, *asInt); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(false); - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - Assert.AreEqual(0b10001011, *asInt); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - Assert.AreEqual(0b1010_10001011, *asInt); - } - - Assert.AreEqual(2, writer.Position); - Assert.AreEqual(0b1010_10001011, *asInt); - - writer.WriteByte(0b11111111); - Assert.AreEqual(0b11111111_00001010_10001011, *asInt); - } - } - [Test] - public unsafe void TestTryBeginWriteBits() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - int* asInt = (int*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asInt); - - using (var bitWriter = writer.EnterBitwiseContext()) - { - Assert.Throws(() => writer.TryBeginWrite(1)); - Assert.Throws(() => writer.TryBeginWriteValue(1)); - Assert.IsTrue(bitWriter.TryBeginWriteBits(1)); - bitWriter.WriteBit(true); - Assert.AreEqual(0b1, *asInt); - - // Can't use Assert.Throws() because ref struct BitWriter can't be captured in a lambda - try - { - bitWriter.WriteBit(true); - } - catch (OverflowException) - { - // Should get called here. - } - - Assert.IsTrue(bitWriter.TryBeginWriteBits(3)); - bitWriter.WriteBit(true); - Assert.AreEqual(0b11, *asInt); - - bitWriter.WriteBit(false); - bitWriter.WriteBit(true); - Assert.AreEqual(0b1011, *asInt); - - try - { - bitWriter.WriteBits(0b11111111, 4); - } - catch (OverflowException) - { - // Should get called here. - } - - try - { - bitWriter.WriteBits(0b11111111, 1); - } - catch (OverflowException) - { - // Should get called here. - } - Assert.IsTrue(bitWriter.TryBeginWriteBits(3)); - - try - { - bitWriter.WriteBits(0b11111111, 4); - } - catch (OverflowException) - { - // Should get called here. - } - Assert.IsTrue(bitWriter.TryBeginWriteBits(4)); - - bitWriter.WriteBits(0b11111010, 3); - - Assert.AreEqual(0b00101011, *asInt); - - Assert.IsTrue(bitWriter.TryBeginWriteBits(5)); - - bitWriter.WriteBits(0b11110101, 5); - Assert.AreEqual(0b1010_10101011, *asInt); - } - - Assert.AreEqual(2, writer.Position); - Assert.AreEqual(0b1010_10101011, *asInt); - - Assert.IsTrue(writer.TryBeginWrite(1)); - writer.WriteByte(0b11111111); - Assert.AreEqual(0b11111111_00001010_10101011, *asInt); - - Assert.IsTrue(writer.TryBeginWrite(1)); - writer.WriteByte(0b00000000); - Assert.AreEqual(0b11111111_00001010_10101011, *asInt); - - Assert.IsFalse(writer.TryBeginWrite(1)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - Assert.IsFalse(bitWriter.TryBeginWriteBits(1)); - } - } - } - - [Test] - public unsafe void TestWritingMultipleBits() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - int* asInt = (int*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asInt); - - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(0b11111111, 1); - Assert.AreEqual(0b1, *asInt); - - bitWriter.WriteBits(0b11111111, 1); - Assert.AreEqual(0b11, *asInt); - - bitWriter.WriteBits(0b11111110, 2); - Assert.AreEqual(0b1011, *asInt); - - bitWriter.WriteBits(0b11111000, 4); - Assert.AreEqual(0b10001011, *asInt); - - bitWriter.WriteBits(0b11111010, 4); - Assert.AreEqual(0b1010_10001011, *asInt); - } - - Assert.AreEqual(2, writer.Position); - Assert.AreEqual(0b1010_10001011, *asInt); - - writer.WriteByte(0b11111111); - Assert.AreEqual(0b11111111_00001010_10001011, *asInt); - } - } - - [Test] - public unsafe void TestWritingMultipleBitsFromLongs() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - int* asInt = (int*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asInt); - - Assert.IsTrue(writer.TryBeginWrite(3)); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(0b11111111UL, 1); - Assert.AreEqual(0b1, *asInt); - - bitWriter.WriteBits(0b11111111UL, 1); - Assert.AreEqual(0b11, *asInt); - - bitWriter.WriteBits(0b11111110UL, 2); - Assert.AreEqual(0b1011, *asInt); - - bitWriter.WriteBits(0b11111000UL, 4); - Assert.AreEqual(0b10001011, *asInt); - - bitWriter.WriteBits(0b11111010UL, 4); - Assert.AreEqual(0b1010_10001011, *asInt); - } - - Assert.AreEqual(2, writer.Position); - Assert.AreEqual(0b1010_10001011, *asInt); - - writer.WriteByte(0b11111111); - Assert.AreEqual(0b11111111_00001010_10001011, *asInt); - } - } - - [Test] - public unsafe void TestWritingMultipleBytesFromLongs([Range(1U, 64U)] uint numBits) - { - var writer = new FastBufferWriter(sizeof(ulong), Allocator.Temp); - using (writer) - { - ulong* asUlong = (ulong*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asUlong); - var mask = 0UL; - for (var i = 0; i < numBits; ++i) - { - mask |= (1UL << i); - } - - ulong value = 0xFFFFFFFFFFFFFFFF; - - Assert.IsTrue(writer.TryBeginWrite(sizeof(ulong))); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(value, numBits); - } - Assert.AreEqual(value & mask, *asUlong); - } - } - - [Test] - public unsafe void TestWritingMultipleBytesFromLongsMisaligned([Range(1U, 63U)] uint numBits) - { - var writer = new FastBufferWriter(sizeof(ulong), Allocator.Temp); - using (writer) - { - ulong* asUlong = (ulong*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asUlong); - var mask = 0UL; - for (var i = 0; i < numBits; ++i) - { - mask |= (1UL << i); - } - - ulong value = 0xFFFFFFFFFFFFFFFF; - - Assert.IsTrue(writer.TryBeginWrite(sizeof(ulong))); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBit(false); - bitWriter.WriteBits(value, numBits); - } - Assert.AreEqual(value & mask, *asUlong >> 1); - } - } - - [Test] - public unsafe void TestWritingBitsThrowsIfTryBeginWriteNotCalled() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - int* asInt = (int*)writer.GetUnsafePtr(); - - Assert.AreEqual(0, *asInt); - - Assert.Throws(() => - { - using var bitWriter = writer.EnterBitwiseContext(); - bitWriter.WriteBit(true); - }); - - Assert.Throws(() => - { - using var bitWriter = writer.EnterBitwiseContext(); - bitWriter.WriteBit(false); - }); - - Assert.Throws(() => - { - using var bitWriter = writer.EnterBitwiseContext(); - bitWriter.WriteBits(0b11111111, 1); - }); - - Assert.Throws(() => - { - using var bitWriter = writer.EnterBitwiseContext(); - bitWriter.WriteBits(0b11111111UL, 1); - }); - - Assert.AreEqual(0, writer.Position); - Assert.AreEqual(0, *asInt); - - writer.WriteByteSafe(0b11111111); - Assert.AreEqual(0b11111111, *asInt); - - - Assert.Throws(() => - { - Assert.IsTrue(writer.TryBeginWrite(1)); - using var bitWriter = writer.EnterBitwiseContext(); - try - { - bitWriter.WriteBits(0b11111111UL, 4); - bitWriter.WriteBits(0b11111111UL, 4); - } - catch (OverflowException) - { - Assert.Fail("Overflow exception was thrown too early."); - } - bitWriter.WriteBits(0b11111111UL, 1); - }); - - } - } - } -} diff --git a/Tests/Editor/Serialization/BitWriterTests.cs.meta b/Tests/Editor/Serialization/BitWriterTests.cs.meta deleted file mode 100644 index 3a8da0e..0000000 --- a/Tests/Editor/Serialization/BitWriterTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fed657e0516a72f469fbf886e3e5149a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/BufferSerializerTests.cs b/Tests/Editor/Serialization/BufferSerializerTests.cs deleted file mode 100644 index b6684ff..0000000 --- a/Tests/Editor/Serialization/BufferSerializerTests.cs +++ /dev/null @@ -1,353 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class BufferSerializerTests - { - [Test] - public void TestIsReaderIsWriter() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - Assert.IsFalse(serializer.IsReader); - Assert.IsTrue(serializer.IsWriter); - } - byte[] readBuffer = new byte[4]; - var reader = new FastBufferReader(readBuffer, Allocator.Temp); - using (reader) - { - var serializer = - new BufferSerializer(new BufferSerializerReader(reader)); - Assert.IsTrue(serializer.IsReader); - Assert.IsFalse(serializer.IsWriter); - } - } - [Test] - public unsafe void TestGetUnderlyingStructs() - { - var writer = new FastBufferWriter(4, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - FastBufferWriter underlyingWriter = serializer.GetFastBufferWriter(); - Assert.IsTrue(underlyingWriter.Handle == writer.Handle); - // Can't use Assert.Throws() because ref structs can't be passed into lambdas. - try - { - serializer.GetFastBufferReader(); - } - catch (InvalidOperationException) - { - // pass - } - - } - byte[] readBuffer = new byte[4]; - var reader = new FastBufferReader(readBuffer, Allocator.Temp); - using (reader) - { - var serializer = - new BufferSerializer(new BufferSerializerReader(reader)); - FastBufferReader underlyingReader = serializer.GetFastBufferReader(); - Assert.IsTrue(underlyingReader.Handle == reader.Handle); - // Can't use Assert.Throws() because ref structs can't be passed into lambdas. - try - { - serializer.GetFastBufferWriter(); - } - catch (InvalidOperationException) - { - // pass - } - } - } - - [Test] - public void TestSerializingValues() - { - var random = new Random(); - int value = random.Next(); - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - serializer.SerializeValue(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - int readValue = 0; - deserializer.SerializeValue(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingBytes() - { - var random = new Random(); - byte value = (byte)random.Next(); - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - serializer.SerializeValue(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - byte readValue = 0; - deserializer.SerializeValue(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingArrays() - { - var random = new Random(); - int[] value = { random.Next(), random.Next(), random.Next() }; - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - serializer.SerializeValue(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - int[] readValue = null; - deserializer.SerializeValue(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingStrings([Values] bool oneBytChars) - { - string value = "I am a test string"; - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - serializer.SerializeValue(ref value, oneBytChars); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - string readValue = null; - deserializer.SerializeValue(ref readValue, oneBytChars); - - Assert.AreEqual(value, readValue); - } - } - } - - - [Test] - public void TestSerializingValuesPreChecked() - { - var random = new Random(); - int value = random.Next(); - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - try - { - serializer.SerializeValuePreChecked(ref value); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(serializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - serializer.SerializeValuePreChecked(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - int readValue = 0; - try - { - deserializer.SerializeValuePreChecked(ref readValue); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(deserializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - deserializer.SerializeValuePreChecked(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingBytesPreChecked() - { - var random = new Random(); - byte value = (byte)random.Next(); - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - try - { - serializer.SerializeValuePreChecked(ref value); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(serializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - serializer.SerializeValuePreChecked(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - byte readValue = 0; - try - { - deserializer.SerializeValuePreChecked(ref readValue); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(deserializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - deserializer.SerializeValuePreChecked(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingArraysPreChecked() - { - var random = new Random(); - int[] value = { random.Next(), random.Next(), random.Next() }; - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - try - { - serializer.SerializeValuePreChecked(ref value); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(serializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - serializer.SerializeValuePreChecked(ref value); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - int[] readValue = null; - try - { - deserializer.SerializeValuePreChecked(ref readValue); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(deserializer.PreCheck(FastBufferWriter.GetWriteSize(value))); - deserializer.SerializeValuePreChecked(ref readValue); - - Assert.AreEqual(value, readValue); - } - } - } - [Test] - public void TestSerializingStringsPreChecked([Values] bool oneBytChars) - { - string value = "I am a test string"; - - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - var serializer = - new BufferSerializer(new BufferSerializerWriter(writer)); - try - { - serializer.SerializeValuePreChecked(ref value, oneBytChars); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(serializer.PreCheck(FastBufferWriter.GetWriteSize(value, oneBytChars))); - serializer.SerializeValuePreChecked(ref value, oneBytChars); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var deserializer = - new BufferSerializer(new BufferSerializerReader(reader)); - string readValue = null; - try - { - deserializer.SerializeValuePreChecked(ref readValue, oneBytChars); - } - catch (OverflowException) - { - // Pass - } - - Assert.IsTrue(deserializer.PreCheck(FastBufferWriter.GetWriteSize(value, oneBytChars))); - deserializer.SerializeValuePreChecked(ref readValue, oneBytChars); - - Assert.AreEqual(value, readValue); - } - } - } - } -} diff --git a/Tests/Editor/Serialization/BufferSerializerTests.cs.meta b/Tests/Editor/Serialization/BufferSerializerTests.cs.meta deleted file mode 100644 index cb62c7e..0000000 --- a/Tests/Editor/Serialization/BufferSerializerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0cf899c97866c76498b71585a61a8142 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/BytePackerTests.cs b/Tests/Editor/Serialization/BytePackerTests.cs deleted file mode 100644 index 192f0db..0000000 --- a/Tests/Editor/Serialization/BytePackerTests.cs +++ /dev/null @@ -1,838 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using NUnit.Framework; -using Unity.Collections; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class BytePackerTests - { - private enum ByteEnum : byte - { - A, - B, - C - } - - private enum SByteEnum : sbyte - { - A, - B, - C - } - - private enum ShortEnum : short - { - A, - B, - C - } - - private enum UShortEnum : ushort - { - A, - B, - C - } - - private enum IntEnum - { - A, - B, - C - } - - private enum UIntEnum : uint - { - A, - B, - C - } - - private enum LongEnum : long - { - A, - B, - C - } - - private enum ULongEnum : ulong - { - A, - B, - C - } - - public enum WriteType - { - WriteDirect, - WriteAsObject - } - - private unsafe void VerifyBytewiseEquality(T value, T otherValue) where T : unmanaged - { - byte* asBytePointer = (byte*)&value; - byte* otherBytePointer = (byte*)&otherValue; - for (var i = 0; i < sizeof(T); ++i) - { - Assert.AreEqual(asBytePointer[i], otherBytePointer[i]); - } - } - - private unsafe void RunTypeTest(T value) where T : unmanaged - { - var writer = new FastBufferWriter(sizeof(T) * 2, Allocator.Temp); - using (writer) - { - BytePacker.WriteValuePacked(writer, (dynamic)value); - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - - var outVal = new T(); - MethodInfo method; - if (value is Enum) - { - method = typeof(ByteUnpacker).GetMethods().Single(x => - x.Name == "ReadValuePacked" && x.IsGenericMethodDefinition) - .MakeGenericMethod(typeof(T)); - } - else - { - method = typeof(ByteUnpacker).GetMethod("ReadValuePacked", - new[] { typeof(FastBufferReader), typeof(T).MakeByRefType() }); - } - - object[] args = { reader, outVal }; - method.Invoke(null, args); - outVal = (T)args[1]; - Assert.AreEqual(value, outVal); - VerifyBytewiseEquality(value, outVal); - } - } - } - - private int GetByteCount64Bits(ulong value) - { - - if (value <= 0b0000_1111) - { - return 1; - } - - if (value <= 0b0000_1111_1111_1111) - { - return 2; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111) - { - return 3; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111) - { - return 4; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111) - { - return 5; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111) - { - return 6; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111) - { - return 7; - } - - if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111) - { - return 8; - } - - return 9; - } - - private int GetByteCount32Bits(uint value) - { - - if (value <= 0b0001_1111) - { - return 1; - } - - if (value <= 0b0001_1111_1111_1111) - { - return 2; - } - - if (value <= 0b0001_1111_1111_1111_1111_1111) - { - return 3; - } - - if (value <= 0b0001_1111_1111_1111_1111_1111_1111_1111) - { - return 4; - } - - return 5; - } - - private int GetByteCount16Bits(ushort value) - { - - if (value <= 0b0011_1111) - { - return 1; - } - if (value <= 0b0011_1111_1111_1111) - { - return 2; - } - - return 3; - } - - private ulong Get64BitEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out ulong value); - return value; - } - } - - private long Get64BitSignedEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out long value); - return value; - } - } - - private uint Get32BitEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out uint value); - return value; - } - } - - private int Get32BitSignedEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out int value); - return value; - } - } - - private ushort Get16BitEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out ushort value); - return value; - } - } - - private short Get16BitSignedEncodedValue(FastBufferWriter writer) - { - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValueBitPacked(reader, out short value); - return value; - } - } - - [Test] - public void TestBitPacking64BitsUnsigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(8); - ulong value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b1111); - Assert.AreEqual(value, Get64BitEncodedValue(writer)); - - for (var i = 0; i < 64; ++i) - { - value = 1UL << i; - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(value), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount64Bits(value), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get64BitEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (1UL << i) | (1UL << j); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(value), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount64Bits(value), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get64BitEncodedValue(writer)); - } - } - } - } - - [Test] - public void TestBitPacking64BitsSigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(8); - long value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b1111); - Assert.AreEqual(value, Get64BitSignedEncodedValue(writer)); - - for (var i = 0; i < 64; ++i) - { - value = 1U << i; - ulong zzvalue = Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get64BitSignedEncodedValue(writer)); - - value = -value; - zzvalue = Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get64BitSignedEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (1U << i) | (1U << j); - zzvalue = Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get64BitSignedEncodedValue(writer)); - - value = -value; - zzvalue = Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get64BitSignedEncodedValue(writer)); - } - } - } - } - - [Test] - public void TestBitPacking32BitsUnsigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(4); - uint value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b111); - Assert.AreEqual(value, Get32BitEncodedValue(writer)); - - for (var i = 0; i < 32; ++i) - { - value = 1U << i; - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(value), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount32Bits(value), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get32BitEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (1U << i) | (1U << j); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(value), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount32Bits(value), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get32BitEncodedValue(writer)); - } - } - } - } - - [Test] - public void TestBitPacking32BitsSigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(4); - int value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b111); - Assert.AreEqual(value, Get32BitEncodedValue(writer)); - - for (var i = 0; i < 32; ++i) - { - value = 1 << i; - uint zzvalue = (uint)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get32BitSignedEncodedValue(writer)); - - value = -value; - zzvalue = (uint)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get32BitSignedEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (1 << i) | (1 << j); - zzvalue = (uint)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get32BitSignedEncodedValue(writer)); - - value = -value; - zzvalue = (uint)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get32BitSignedEncodedValue(writer)); - } - } - } - } - - [Test] - public void TestBitPacking16BitsUnsigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(2); - ushort value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b11); - Assert.AreEqual(value, Get16BitEncodedValue(writer)); - - for (var i = 0; i < 16; ++i) - { - value = (ushort)(1U << i); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(value), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount16Bits(value), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get16BitEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (ushort)((1U << i) | (1U << j)); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(value), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount16Bits(value), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get16BitEncodedValue(writer)); - } - } - } - } - [Test] - public void TestBitPacking16BitsSigned() - { - var writer = new FastBufferWriter(9, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(2); - short value = 0; - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(1, writer.Position); - Assert.AreEqual(1, writer.ToArray()[0] & 0b11); - Assert.AreEqual(value, Get16BitEncodedValue(writer)); - - for (var i = 0; i < 16; ++i) - { - value = (short)(1 << i); - ushort zzvalue = (ushort)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get16BitSignedEncodedValue(writer)); - - value = (short)-value; - zzvalue = (ushort)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i})"); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})"); - Assert.AreEqual(value, Get16BitSignedEncodedValue(writer)); - - for (var j = 0; j < 8; ++j) - { - value = (short)((1 << i) | (1 << j)); - zzvalue = (ushort)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get16BitSignedEncodedValue(writer)); - - value = (short)-value; - zzvalue = (ushort)Arithmetic.ZigZagEncode(value); - writer.Seek(0); - writer.Truncate(); - BytePacker.WriteValueBitPacked(writer, value); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})"); - Assert.AreEqual(value, Get16BitSignedEncodedValue(writer)); - } - } - } - } - - [Test] - public void TestPackingBasicTypes( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), typeof(Vector4), - typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D))] - Type testType, - [Values] WriteType writeType) - { - var random = new Random(); - - if (testType == typeof(byte)) - { - byte b = (byte)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(b); - } - } - else if (testType == typeof(sbyte)) - { - sbyte sb = (sbyte)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(sb); - } - } - else if (testType == typeof(short)) - { - short s = (short)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(s); - } - } - else if (testType == typeof(ushort)) - { - ushort us = (ushort)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(us); - } - } - else if (testType == typeof(int)) - { - int i = random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(i); - } - } - else if (testType == typeof(uint)) - { - uint ui = (uint)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(ui); - } - } - else if (testType == typeof(long)) - { - long l = ((long)random.Next() << 32) + random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(l); - } - } - else if (testType == typeof(ulong)) - { - ulong ul = ((ulong)random.Next() << 32) + (ulong)random.Next(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(ul); - } - } - else if (testType == typeof(bool)) - { - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(true); - } - } - else if (testType == typeof(char)) - { - char c = 'a'; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(c); - } - - c = '\u263a'; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(c); - } - } - else if (testType == typeof(float)) - { - float f = (float)random.NextDouble(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(f); - } - } - else if (testType == typeof(double)) - { - double d = random.NextDouble(); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(d); - } - } - else if (testType == typeof(ByteEnum)) - { - ByteEnum e = ByteEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(SByteEnum)) - { - SByteEnum e = SByteEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(ShortEnum)) - { - ShortEnum e = ShortEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(UShortEnum)) - { - UShortEnum e = UShortEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(IntEnum)) - { - IntEnum e = IntEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(UIntEnum)) - { - UIntEnum e = UIntEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(LongEnum)) - { - LongEnum e = LongEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(ULongEnum)) - { - ULongEnum e = ULongEnum.C; - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(e); - } - } - else if (testType == typeof(Vector2)) - { - var v = new Vector2((float)random.NextDouble(), (float)random.NextDouble()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Vector3)) - { - var v = new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Vector4)) - { - var v = new Vector4((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Quaternion)) - { - var v = new Quaternion((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Color)) - { - var v = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Color32)) - { - var v = new Color32((byte)random.Next(), (byte)random.Next(), (byte)random.Next(), (byte)random.Next()); - if (writeType == WriteType.WriteDirect) - { - RunTypeTest(v); - } - } - else if (testType == typeof(Ray)) - { - // Rays need special handling on the equality checks because the constructor normalizes direction - // Which can cause slight variations in the result - var v = new Ray( - new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()), - new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble())); - if (writeType == WriteType.WriteDirect) - { - unsafe - { - var writer = new FastBufferWriter(sizeof(Ray) * 2, Allocator.Temp); - using (writer) - { - BytePacker.WriteValuePacked(writer, v); - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValuePacked(reader, out Ray outVal); - Assert.AreEqual(v.origin, outVal.origin); - Assert.AreEqual(v.direction.x, outVal.direction.x, 0.00001); - Assert.AreEqual(v.direction.y, outVal.direction.y, 0.00001); - Assert.AreEqual(v.direction.z, outVal.direction.z, 0.00001); - } - } - } - } - } - else if (testType == typeof(Ray2D)) - { - // Rays need special handling on the equality checks because the constructor normalizes direction - // Which can cause slight variations in the result - var v = new Ray2D( - new Vector2((float)random.NextDouble(), (float)random.NextDouble()), - new Vector2((float)random.NextDouble(), (float)random.NextDouble())); - if (writeType == WriteType.WriteDirect) - { - unsafe - { - var writer = new FastBufferWriter(sizeof(Ray2D) * 2, Allocator.Temp); - using (writer) - { - BytePacker.WriteValuePacked(writer, v); - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - ByteUnpacker.ReadValuePacked(reader, out Ray2D outVal); - Assert.AreEqual(v.origin, outVal.origin); - Assert.AreEqual(v.direction.x, outVal.direction.x, 0.00001); - Assert.AreEqual(v.direction.y, outVal.direction.y, 0.00001); - } - } - } - } - } - else - { - Assert.Fail("No type handler was provided for this type in the test!"); - } - } - } -} diff --git a/Tests/Editor/Serialization/BytePackerTests.cs.meta b/Tests/Editor/Serialization/BytePackerTests.cs.meta deleted file mode 100644 index 4c07179..0000000 --- a/Tests/Editor/Serialization/BytePackerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b50db056cd7443b4eb2e00b603d4c15c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/FastBufferReaderTests.cs b/Tests/Editor/Serialization/FastBufferReaderTests.cs deleted file mode 100644 index 30b1ba8..0000000 --- a/Tests/Editor/Serialization/FastBufferReaderTests.cs +++ /dev/null @@ -1,1583 +0,0 @@ -using System; -using System.Reflection; -using NUnit.Framework; -using Unity.Collections; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class FastBufferReaderTests : BaseFastBufferReaderWriterTest - { - private void WriteCheckBytes(FastBufferWriter writer, int writeSize, string failMessage = "") - { - Assert.IsTrue(writer.TryBeginWrite(2), "Writer denied write permission"); - writer.WriteValue((byte)0x80); - Assert.AreEqual(writeSize + 1, writer.Position, failMessage); - Assert.AreEqual(writeSize + 1, writer.Length, failMessage); - writer.WriteValue((byte)0xFF); - Assert.AreEqual(writeSize + 2, writer.Position, failMessage); - Assert.AreEqual(writeSize + 2, writer.Length, failMessage); - } - - private void VerifyCheckBytes(FastBufferReader reader, int checkPosition, string failMessage = "") - { - reader.Seek(checkPosition); - reader.TryBeginRead(2); - - reader.ReadByte(out byte value); - Assert.AreEqual(0x80, value, failMessage); - reader.ReadByte(out value); - Assert.AreEqual(0xFF, value, failMessage); - } - - private void VerifyPositionAndLength(FastBufferReader reader, int length, string failMessage = "") - { - Assert.AreEqual(0, reader.Position, failMessage); - Assert.AreEqual(length, reader.Length, failMessage); - } - - private FastBufferReader CommonChecks(FastBufferWriter writer, T valueToTest, int writeSize, string failMessage = "") where T : unmanaged - { - WriteCheckBytes(writer, writeSize, failMessage); - - var reader = new FastBufferReader(writer, Allocator.Temp); - - VerifyPositionAndLength(reader, writer.Length, failMessage); - - VerifyCheckBytes(reader, writeSize, failMessage); - - reader.Seek(0); - - return reader; - } - - private void RunWriteMethod(string methodName, FastBufferWriter writer, in T value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(T).MakeByRefType() }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsArray) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - - private void RunWriteMethod(string methodName, FastBufferWriter writer, in T[] value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(T[]) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.IsArray) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - - private void RunWriteMethod(string methodName, FastBufferWriter writer, in NativeArray value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(NativeArray) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeArray")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - private void RunWriteMethod(string methodName, FastBufferWriter writer, in NativeList value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(NativeList) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeList")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } -#endif - - private void RunReadMethod(string methodName, FastBufferReader reader, out T value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferReader).GetMethod(methodName, new[] { typeof(T).MakeByRefType() }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferReader).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsArray) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - value = new T(); - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(reader, args); - value = (T)args[0]; - } - - private void RunReadMethod(string methodName, FastBufferReader reader, out T[] value) where T : unmanaged - { - MethodInfo method = null; - - try - { - method = typeof(FastBufferReader).GetMethod(methodName, new[] { typeof(T[]).MakeByRefType() }); - } - catch (AmbiguousMatchException) - { - // skip. - } - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferReader).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.HasElementType || !candidateMethod.GetParameters()[0].ParameterType.GetElementType().IsArray) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - value = new T[] { }; - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(reader, args); - value = (T[])args[0]; - } - - private void RunReadMethod(string methodName, FastBufferReader reader, out NativeArray value) where T : unmanaged - { - MethodInfo method = null; - - try - { - method = typeof(FastBufferReader).GetMethod(methodName, new[] { typeof(NativeArray).MakeByRefType(), typeof(Allocator) }); - } - catch (AmbiguousMatchException) - { - // skip. - } - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferReader).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length < 2 || (candidateMethod.GetParameters().Length > 2 && !candidateMethod.GetParameters()[2].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeArray")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - value = new NativeArray(); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - args[1] = Allocator.Temp; - for (var i = 2; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(reader, args); - value = (NativeArray)args[0]; - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - private void RunReadMethod(string methodName, FastBufferReader reader, ref NativeList value) where T : unmanaged - { - MethodInfo method = null; - - try - { - method = typeof(FastBufferReader).GetMethod(methodName, new[] { typeof(NativeList).MakeByRefType() }); - } - catch (AmbiguousMatchException) - { - // skip. - } - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferReader).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeList")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(reader, args); - } -#endif - - protected override unsafe void RunTypeTest(T valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - Assert.AreEqual(sizeof(T), writeSize); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - - using (writer) - { - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - var failMessage = $"RunTypeTest failed with type {typeof(T)} and value {valueToTest}"; - - RunWriteMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - - var reader = CommonChecks(writer, valueToTest, writeSize, failMessage); - - using (reader) - { - Assert.IsTrue(reader.TryBeginRead(FastBufferWriter.GetWriteSize())); - RunReadMethod(nameof(FastBufferReader.ReadValue), reader, out T result); - Assert.AreEqual(valueToTest, result); - } - } - } - protected override unsafe void RunTypeTestSafe(T valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - - using (writer) - { - Assert.AreEqual(sizeof(T), writeSize); - - var failMessage = $"RunTypeTest failed with type {typeof(T)} and value {valueToTest}"; - - RunWriteMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - - - var reader = CommonChecks(writer, valueToTest, writeSize, failMessage); - - using (reader) - { - RunReadMethod(nameof(FastBufferReader.ReadValueSafe), reader, out T result); - Assert.AreEqual(valueToTest, result); - } - } - } - - private void VerifyArrayEquality(T[] value, T[] compareValue, int offset) where T : unmanaged - { - Assert.AreEqual(value.Length, compareValue.Length); - - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(value[i], compareValue[i]); - } - } - - private void VerifyArrayEquality(NativeArray value, NativeArray compareValue, int offset) where T : unmanaged - { - Assert.AreEqual(value.Length, compareValue.Length); - - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(value[i], compareValue[i]); - } - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - private void VerifyArrayEquality(NativeList value, NativeList compareValue, int offset) where T : unmanaged - { - Assert.AreEqual(value.Length, compareValue.Length); - - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(value[i], compareValue[i]); - } - } -#endif - - protected override unsafe void RunTypeArrayTest(T[] valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunWriteMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - Assert.IsTrue(reader.TryBeginRead(writeSize)); - RunReadMethod(nameof(FastBufferReader.ReadValue), reader, out T[] result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } - - protected override unsafe void RunTypeArrayTestSafe(T[] valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunWriteMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - RunReadMethod(nameof(FastBufferReader.ReadValueSafe), reader, out T[] result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } - - protected override unsafe void RunTypeNativeArrayTest(NativeArray valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunWriteMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - Assert.IsTrue(reader.TryBeginRead(writeSize)); - RunReadMethod(nameof(FastBufferReader.ReadValue), reader, out NativeArray result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } - - protected override unsafe void RunTypeNativeArrayTestSafe(NativeArray valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunWriteMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - RunReadMethod(nameof(FastBufferReader.ReadValueSafe), reader, out NativeArray result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - protected override unsafe void RunTypeNativeListTest(NativeList valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunWriteMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - Assert.IsTrue(reader.TryBeginRead(writeSize)); - var result = new NativeList(Allocator.Temp); - RunReadMethod(nameof(FastBufferReader.ReadValueInPlace), reader, ref result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } - - protected override unsafe void RunTypeNativeListTestSafe(NativeList valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunWriteMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - - WriteCheckBytes(writer, writeSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - var result = new NativeList(Allocator.Temp); - RunReadMethod(nameof(FastBufferReader.ReadValueSafeInPlace), reader, ref result); - VerifyArrayEquality(valueToTest, result, 0); - - VerifyCheckBytes(reader, writeSize); - } - } - } -#endif - - [Test] - public void GivenFastBufferWriterContainingValue_WhenReadingUnmanagedType_ValueMatchesWhatWasWritten( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseTypeTest(testType, writeType); - } - - [Test] - public void GivenFastBufferWriterContainingValue_WhenReadingArrayOfUnmanagedElementType_ValueMatchesWhatWasWritten( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseArrayTypeTest(testType, writeType); - } - - [Test] - public void GivenFastBufferWriterContainingValue_WhenReadingNativeArrayOfUnmanagedElementType_ValueMatchesWhatWasWritten( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseNativeArrayTypeTest(testType, writeType); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [Test] - public void GivenFastBufferWriterContainingValue_WhenReadingNativeListOfUnmanagedElementType_ValueMatchesWhatWasWritten( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseNativeListTypeTest(testType, writeType); - } -#endif - - public unsafe void RunFixedStringTest(T fixedStringValue, int numBytesWritten, WriteType writeType) where T : unmanaged, INativeList, IUTF8Bytes - { - fixedStringValue.Length = numBytesWritten; - - var serializedValueSize = FastBufferWriter.GetWriteSize(fixedStringValue); - - Assert.AreEqual(serializedValueSize, fixedStringValue.Length + sizeof(int)); - - var writer = new FastBufferWriter(serializedValueSize + 3, Allocator.Temp); - using (writer) - { - var offset = 0; - switch (writeType) - { - case WriteType.WriteDirect: - Assert.IsTrue(writer.TryBeginWrite(serializedValueSize + 2), "Writer denied write permission"); - writer.WriteValue(fixedStringValue); - break; - case WriteType.WriteSafe: - writer.WriteValueSafe(fixedStringValue); - break; - - } - - WriteCheckBytes(writer, serializedValueSize + offset); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - var result = new T(); - reader.ReadValueSafe(out result); - Assert.AreEqual(fixedStringValue, result); - - VerifyCheckBytes(reader, serializedValueSize); - } - } - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - public void WhenReadingFixedString32Bytes_ValueIsReadCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 29; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString32Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - public void WhenReadingFixedString64Bytes_ValueIsReadCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 61; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString64Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - public void WhenReadingFixedString128Bytes_ValueIsReadCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 125; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString128Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - [TestCase(509, WriteType.WriteSafe)] - public void WhenReadingFixedString512Bytes_ValueIsReadCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 509; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString512Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - [TestCase(509, WriteType.WriteSafe)] - [TestCase(4093, WriteType.WriteSafe)] - public void WhenReadingFixedString4096Bytes_ValueIsReadCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 4093; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString4096Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(false, WriteType.WriteDirect)] - [TestCase(false, WriteType.WriteSafe)] - [TestCase(true, WriteType.WriteDirect)] - [TestCase(true, WriteType.WriteSafe)] - public void GivenFastBufferWriterContainingValue_WhenReadingString_ValueMatchesWhatWasWritten(bool oneByteChars, WriteType writeType) - { - string valueToTest = "Hello, I am a test string!"; - - var serializedValueSize = FastBufferWriter.GetWriteSize(valueToTest, oneByteChars); - - var writer = new FastBufferWriter(serializedValueSize + 3, Allocator.Temp); - using (writer) - { - switch (writeType) - { - case WriteType.WriteDirect: - Assert.IsTrue(writer.TryBeginWrite(serializedValueSize + 2), "Writer denied write permission"); - writer.WriteValue(valueToTest, oneByteChars); - break; - case WriteType.WriteSafe: - writer.WriteValueSafe(valueToTest, oneByteChars); - break; - } - - WriteCheckBytes(writer, serializedValueSize); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length); - - string result = null; - switch (writeType) - { - case WriteType.WriteDirect: - Assert.IsTrue(reader.TryBeginRead(serializedValueSize + 2), "Reader denied read permission"); - reader.ReadValue(out result, oneByteChars); - break; - case WriteType.WriteSafe: - reader.ReadValueSafe(out result, oneByteChars); - break; - } - Assert.AreEqual(valueToTest, result); - - VerifyCheckBytes(reader, serializedValueSize); - } - } - } - - - [TestCase(1, 0)] - [TestCase(2, 0)] - [TestCase(3, 0)] - [TestCase(4, 0)] - [TestCase(5, 0)] - [TestCase(6, 0)] - [TestCase(7, 0)] - [TestCase(8, 0)] - - [TestCase(1, 1)] - [TestCase(2, 1)] - [TestCase(3, 1)] - [TestCase(4, 1)] - [TestCase(5, 1)] - [TestCase(6, 1)] - [TestCase(7, 1)] - - [TestCase(1, 2)] - [TestCase(2, 2)] - [TestCase(3, 2)] - [TestCase(4, 2)] - [TestCase(5, 2)] - [TestCase(6, 2)] - - [TestCase(1, 3)] - [TestCase(2, 3)] - [TestCase(3, 3)] - [TestCase(4, 3)] - [TestCase(5, 3)] - - [TestCase(1, 4)] - [TestCase(2, 4)] - [TestCase(3, 4)] - [TestCase(4, 4)] - - [TestCase(1, 5)] - [TestCase(2, 5)] - [TestCase(3, 5)] - - [TestCase(1, 6)] - [TestCase(2, 6)] - - [TestCase(1, 7)] - public void GivenFastBufferWriterContainingValue_WhenReadingPartialValue_ValueMatchesWhatWasWritten(int count, int offset) - { - var random = new Random(); - var valueToTest = ((ulong)random.Next() << 32) + (ulong)random.Next(); - var writer = new FastBufferWriter(sizeof(ulong) + 2, Allocator.Temp); - using (writer) - { - Assert.IsTrue(writer.TryBeginWrite(count + 2), "Writer denied write permission"); - writer.WritePartialValue(valueToTest, count, offset); - - var failMessage = $"TestReadingPartialValues failed with value {valueToTest}"; - WriteCheckBytes(writer, count, failMessage); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - VerifyPositionAndLength(reader, writer.Length, failMessage); - Assert.IsTrue(reader.TryBeginRead(count + 2), "Reader denied read permission"); - - ulong mask = 0; - for (var i = 0; i < count; ++i) - { - mask = (mask << 8) | 0b11111111; - } - - mask <<= (offset * 8); - - reader.ReadPartialValue(out ulong result, count, offset); - Assert.AreEqual(valueToTest & mask, result & mask, failMessage); - VerifyCheckBytes(reader, count, failMessage); - } - } - } - - - [Test] - public unsafe void GivenFastBufferReaderInitializedFromFastBufferWriterContainingValue_WhenCallingToArray_ReturnedArrayMatchesContentOfWriter() - { - var testStruct = GetTestStruct(); - var requiredSize = FastBufferWriter.GetWriteSize(testStruct); - var writer = new FastBufferWriter(requiredSize, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(requiredSize); - writer.WriteValue(testStruct); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - var array = reader.ToArray(); - var underlyingArray = writer.GetUnsafePtr(); - for (var i = 0; i < array.Length; ++i) - { - Assert.AreEqual(array[i], underlyingArray[i]); - } - } - } - } - - [Test] - public void WhenCreatingAReaderFromAnEmptyArraySegment_LengthIsZero() - { - var bytes = new byte[] { }; - var input = new ArraySegment(bytes, 0, 0); - using var reader = new FastBufferReader(input, Allocator.Temp); - Assert.AreEqual(0, reader.Length); - } - - [Test] - public void WhenCreatingAReaderFromAnEmptyArray_LengthIsZero() - { - var input = new byte[] { }; - using var reader = new FastBufferReader(input, Allocator.Temp); - Assert.AreEqual(0, reader.Length); - } - - [Test] - public void WhenCreatingAReaderFromAnEmptyNativeArray_LengthIsZero() - { - var input = new NativeArray(0, Allocator.Temp); - using var reader = new FastBufferReader(input, Allocator.Temp); - Assert.AreEqual(0, reader.Length); - } - - [Test] - public void WhenCreatingAReaderFromAnEmptyFastBufferWriter_LengthIsZero() - { - var input = new FastBufferWriter(0, Allocator.Temp); - using var reader = new FastBufferReader(input, Allocator.Temp); - Assert.AreEqual(0, reader.Length); - } - - [Test] - public void WhenCreatingAReaderFromAnEmptyBuffer_LengthIsZero() - { - var input = new byte[] { }; - unsafe - { - fixed (byte* ptr = input) - { - using var reader = new FastBufferReader(ptr, Allocator.Temp, 0); - Assert.AreEqual(0, reader.Length); - } - } - } - - [Test] - public void WhenCreatingNewFastBufferReader_IsInitializedIsTrue() - { - var array = new NativeArray(100, Allocator.Temp); - var reader = new FastBufferReader(array, Allocator.Temp); - Assert.AreEqual(true, reader.IsInitialized); - reader.Dispose(); - array.Dispose(); - } - - [Test] - public void WhenDisposingFastBufferReader_IsInitializedIsFalse() - { - var array = new NativeArray(100, Allocator.Temp); - var reader = new FastBufferReader(array, Allocator.Temp); - reader.Dispose(); - Assert.AreEqual(false, reader.IsInitialized); - array.Dispose(); - Assert.AreEqual(false, reader.IsInitialized); - } - - [Test] - public void WhenUsingDefaultFastBufferReader_IsInitializedIsFalse() - { - FastBufferReader writer = default; - Assert.AreEqual(false, writer.IsInitialized); - } - - [Test] - public void WhenCallingReadByteWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - Assert.Throws(() => { emptyReader.ReadByte(out byte b); }); - } - } - - [Test] - public void WhenCallingReadBytesWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - byte[] b = { 0, 1, 2 }; - using (emptyReader) - { - Assert.Throws(() => { emptyReader.ReadBytes(ref b, 3); }); - } - } - - [Test] - public void WhenCallingReadValueWithUnmanagedTypeWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - Assert.Throws(() => { emptyReader.ReadValue(out int i); }); - } - } - - [Test] - public void WhenCallingReadValueWithByteArrayWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - Assert.Throws(() => { emptyReader.ReadValue(out byte[] b); }); - } - } - - [Test] - public void WhenCallingReadValueWithStringWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - Assert.Throws(() => { emptyReader.ReadValue(out string s); }); - } - } - - [Test] - public void WhenCallingReadValueAfterCallingTryBeginWriteWithTooFewBytes_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(sizeof(int) - 1); - Assert.Throws(() => { emptyReader.ReadValue(out int i); }); - } - } - - [Test] - public void WhenCallingReadBytePastBoundaryMarkedByTryBeginWrite_OverflowExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(sizeof(int) - 1); - emptyReader.ReadByte(out byte b); - emptyReader.ReadByte(out b); - emptyReader.ReadByte(out b); - Assert.Throws(() => { emptyReader.ReadByte(out b); }); - } - } - - [Test] - public void WhenCallingReadByteDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadByte(out byte b); }); - } - } - - [Test] - public void WhenCallingReadBytesDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - byte[] b = { 0, 1, 2 }; - Assert.Throws(() => { emptyReader.ReadBytes(ref b, 3); }); - } - } - - [Test] - public void WhenCallingReadValueWithUnmanagedTypeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValue(out int i); }); - } - } - - [Test] - public void WhenCallingReadValueWithByteArrayDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValue(out byte[] b); }); - } - } - - [Test] - public void WhenCallingReadValueWithStringDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValue(out string s); }); - } - } - - [Test] - public void WhenCallingReadByteSafeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadByteSafe(out byte b); }); - } - } - - [Test] - public void WhenCallingReadBytesSafeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - byte[] b = { 0, 1, 2 }; - Assert.Throws(() => { emptyReader.ReadBytesSafe(ref b, 3); }); - } - } - - [Test] - public void WhenCallingReadValueSafeWithUnmanagedTypeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValueSafe(out int i); }); - } - } - - [Test] - public void WhenCallingReadValueSafeWithByteArrayDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValueSafe(out byte[] b); }); - } - } - - [Test] - public void WhenCallingReadValueSafeWithStringDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - using var context = emptyReader.EnterBitwiseContext(); - Assert.Throws(() => { emptyReader.ReadValueSafe(out string s); }); - } - } - - [Test] - public void WhenCallingReadByteAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadByte(out byte theByte); - } - } - - [Test] - public void WhenCallingReadBytesAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - - byte[] theBytes = { 0, 1, 2 }; - emptyReader.ReadBytes(ref theBytes, 3); - } - } - - [Test] - public void WhenCallingReadValueWithUnmanagedTypeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValue(out int i); - } - } - - [Test] - public void WhenCallingReadValueWithByteArrayAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValue(out byte[] theBytes); - } - } - - [Test] - public void WhenCallingReadValueWithStringAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValue(out string s); - } - } - - [Test] - public void WhenCallingReadByteSafeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadByteSafe(out byte theByte); - } - } - - [Test] - public void WhenCallingReadBytesSafeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - - byte[] theBytes = { 0, 1, 2 }; - emptyReader.ReadBytesSafe(ref theBytes, 3); - } - } - - [Test] - public void WhenCallingReadValueSafeWithUnmanagedTypeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValueSafe(out int i); - } - } - - [Test] - public void WhenCallingReadValueSafeWithByteArrayAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValueSafe(out byte[] theBytes); - } - } - - [Test] - public void WhenCallingReadValueSafeWithStringAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - using (var context = emptyReader.EnterBitwiseContext()) - { - context.ReadBit(out bool theBit); - } - emptyReader.ReadValueSafe(out string s); - } - } - - [Test] - public void WhenCallingTryBeginRead_TheAllowedReadPositionIsMarkedRelativeToCurrentPosition() - { - var nativeArray = new NativeArray(100, Allocator.Temp); - var emptyReader = new FastBufferReader(nativeArray, Allocator.Temp); - - using (emptyReader) - { - emptyReader.TryBeginRead(100); - emptyReader.ReadByte(out byte b); - emptyReader.TryBeginRead(1); - emptyReader.ReadByte(out b); - Assert.Throws(() => { emptyReader.ReadByte(out byte b); }); - } - } - - [Test] - public void WhenReadingAfterSeeking_TheNewReadComesFromTheCorrectPosition() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.WriteByteSafe(1); - writer.WriteByteSafe(3); - writer.WriteByteSafe(2); - writer.WriteByteSafe(5); - writer.WriteByteSafe(4); - writer.WriteByteSafe(0); - - var reader = new FastBufferReader(writer, Allocator.Temp); - using (reader) - { - reader.Seek(5); - reader.ReadByteSafe(out byte b); - Assert.AreEqual(reader.Position, 6); - Assert.AreEqual(reader.Length, writer.Length); - Assert.AreEqual(0, b); - - reader.Seek(0); - reader.ReadByteSafe(out b); - Assert.AreEqual(reader.Position, 1); - Assert.AreEqual(reader.Length, writer.Length); - Assert.AreEqual(1, b); - - reader.Seek(10); - Assert.AreEqual(reader.Position, writer.Length); - Assert.AreEqual(reader.Length, writer.Length); - - reader.Seek(2); - reader.ReadByteSafe(out b); - Assert.AreEqual(2, b); - - reader.Seek(1); - reader.ReadByteSafe(out b); - Assert.AreEqual(3, b); - - reader.Seek(4); - reader.ReadByteSafe(out b); - Assert.AreEqual(4, b); - - reader.Seek(3); - reader.ReadByteSafe(out b); - Assert.AreEqual(5, b); - - Assert.AreEqual(reader.Position, 4); - Assert.AreEqual(reader.Length, writer.Length); - } - } - } - - [Test] - public unsafe void WhenCallingTryBeginReadInternal_AllowedReadPositionDoesNotMoveBackward() - { - var reader = new FastBufferReader(new NativeArray(100, Allocator.Temp), Allocator.Temp); - using (reader) - { - reader.TryBeginRead(25); - reader.TryBeginReadInternal(5); - Assert.AreEqual(reader.Handle->AllowedReadMark, 25); - } - } - } -} diff --git a/Tests/Editor/Serialization/FastBufferReaderTests.cs.meta b/Tests/Editor/Serialization/FastBufferReaderTests.cs.meta deleted file mode 100644 index 52af796..0000000 --- a/Tests/Editor/Serialization/FastBufferReaderTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2881f8138b479c34389b76687e5307ab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/FastBufferWriterTests.cs b/Tests/Editor/Serialization/FastBufferWriterTests.cs deleted file mode 100644 index 98d4231..0000000 --- a/Tests/Editor/Serialization/FastBufferWriterTests.cs +++ /dev/null @@ -1,1556 +0,0 @@ -using System; -using System.Reflection; -using NUnit.Framework; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class FastBufferWriterTests : BaseFastBufferReaderWriterTest - { - private void WriteCheckBytes(FastBufferWriter writer, int writeSize, string failMessage = "") - { - Assert.IsTrue(writer.TryBeginWrite(2), "Writer denied write permission"); - writer.WriteValue((byte)0x80); - Assert.AreEqual(writeSize + 1, writer.Position, failMessage); - Assert.AreEqual(writeSize + 1, writer.Length, failMessage); - writer.WriteValue((byte)0xFF); - Assert.AreEqual(writeSize + 2, writer.Position, failMessage); - Assert.AreEqual(writeSize + 2, writer.Length, failMessage); - } - - private void VerifyCheckBytes(byte[] underlyingArray, int writeSize, string failMessage = "") - { - Assert.AreEqual(0x80, underlyingArray[writeSize], failMessage); - Assert.AreEqual(0xFF, underlyingArray[writeSize + 1], failMessage); - } - - private unsafe void VerifyBytewiseEquality(T value, byte[] underlyingArray, int valueOffset, int bufferOffset, int size, string failMessage = "") where T : unmanaged - { - byte* asBytePointer = (byte*)&value; - for (var i = 0; i < size; ++i) - { - Assert.AreEqual(asBytePointer[i + valueOffset], underlyingArray[i + bufferOffset], failMessage); - } - } - - private unsafe void VerifyTypedEquality(T value, byte* unsafePtr) where T : unmanaged - { - var checkValue = (T*)unsafePtr; - Assert.AreEqual(value, *checkValue); - } - - private void VerifyPositionAndLength(FastBufferWriter writer, int position, string failMessage = "") - { - Assert.AreEqual(position, writer.Position, failMessage); - Assert.AreEqual(position, writer.Length, failMessage); - } - - private unsafe void CommonChecks(FastBufferWriter writer, T valueToTest, int writeSize, string failMessage = "") where T : unmanaged - { - - VerifyPositionAndLength(writer, writeSize, failMessage); - - WriteCheckBytes(writer, writeSize, failMessage); - - var underlyingArray = writer.ToArray(); - - VerifyBytewiseEquality(valueToTest, underlyingArray, 0, 0, writeSize, failMessage); - - VerifyCheckBytes(underlyingArray, writeSize, failMessage); - - VerifyTypedEquality(valueToTest, writer.GetUnsafePtr()); - } - - private void RunMethod(string methodName, FastBufferWriter writer, in T value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(T).MakeByRefType() }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsArray) - { - continue; - } - - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - - private void RunMethod(string methodName, FastBufferWriter writer, in T[] value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(T[]) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.IsArray) - { - continue; - } - if (candidateMethod.GetParameters()[0].ParameterType.IsGenericType) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - - private void RunMethod(string methodName, FastBufferWriter writer, in NativeArray value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(NativeArray) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeArray")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - private void RunMethod(string methodName, FastBufferWriter writer, in NativeList value) where T : unmanaged - { - MethodInfo method = typeof(FastBufferWriter).GetMethod(methodName, new[] { typeof(NativeList) }); - if (method == null) - { - foreach (var candidateMethod in typeof(FastBufferWriter).GetMethods()) - { - if (candidateMethod.Name == methodName && candidateMethod.IsGenericMethodDefinition) - { - if (candidateMethod.GetParameters().Length == 0 || (candidateMethod.GetParameters().Length > 1 && !candidateMethod.GetParameters()[1].HasDefaultValue)) - { - continue; - } - if (!candidateMethod.GetParameters()[0].ParameterType.Name.Contains("NativeList")) - { - continue; - } - try - { - method = candidateMethod.MakeGenericMethod(typeof(T)); - break; - } - catch (ArgumentException) - { - continue; - } - } - } - } - - Assert.NotNull(method); - - object[] args = new object[method.GetParameters().Length]; - args[0] = value; - for (var i = 1; i < args.Length; ++i) - { - args[i] = method.GetParameters()[i].DefaultValue; - } - method.Invoke(writer, args); - } -#endif - - - protected override unsafe void RunTypeTest(T valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var alternateWriteSize = FastBufferWriter.GetWriteSize(); - Assert.AreEqual(sizeof(T), writeSize); - Assert.AreEqual(sizeof(T), alternateWriteSize); - - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - - using (writer) - { - - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - var failMessage = $"RunTypeTest failed with type {typeof(T)} and value {valueToTest}"; - - RunMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - - CommonChecks(writer, valueToTest, writeSize, failMessage); - } - } - protected override unsafe void RunTypeTestSafe(T valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - - using (writer) - { - Assert.AreEqual(sizeof(T), writeSize); - - var failMessage = $"RunTypeTest failed with type {typeof(T)} and value {valueToTest}"; - - RunMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - - CommonChecks(writer, valueToTest, writeSize, failMessage); - } - } - - private unsafe void VerifyArrayEquality(T[] value, byte* unsafePtr, int offset) where T : unmanaged - { - int* sizeValue = (int*)(unsafePtr + offset); - Assert.AreEqual(value.Length, *sizeValue); - - fixed (T* asTPointer = value) - { - var underlyingTArray = (T*)(unsafePtr + sizeof(int) + offset); - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(asTPointer[i], underlyingTArray[i]); - } - } - } - - private unsafe void VerifyArrayEquality(NativeArray value, byte* unsafePtr, int offset) where T : unmanaged - { - int* sizeValue = (int*)(unsafePtr + offset); - Assert.AreEqual(value.Length, *sizeValue); - - var asTPointer = (T*)value.GetUnsafePtr(); - var underlyingTArray = (T*)(unsafePtr + sizeof(int) + offset); - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(asTPointer[i], underlyingTArray[i]); - } - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - private unsafe void VerifyArrayEquality(NativeList value, byte* unsafePtr, int offset) where T : unmanaged - { - int* sizeValue = (int*)(unsafePtr + offset); - Assert.AreEqual(value.Length, *sizeValue); -#if UTP_TRANSPORT_2_0_ABOVE - var asTPointer = value.GetUnsafePtr(); -#else - var asTPointer = (T*)value.GetUnsafePtr(); -#endif - var underlyingTArray = (T*)(unsafePtr + sizeof(int) + offset); - for (var i = 0; i < value.Length; ++i) - { - Assert.AreEqual(asTPointer[i], underlyingTArray[i]); - } - } -#endif - - protected override unsafe void RunTypeArrayTest(T[] valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } - - protected override unsafe void RunTypeArrayTestSafe(T[] valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } - - - protected override unsafe void RunTypeNativeArrayTest(NativeArray valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } - - protected override unsafe void RunTypeNativeArrayTestSafe(NativeArray valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } - - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - protected override unsafe void RunTypeNativeListTest(NativeList valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - Assert.IsTrue(writer.TryBeginWrite(writeSize + 2), "Writer denied write permission"); - - RunMethod(nameof(FastBufferWriter.WriteValue), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } - - protected override unsafe void RunTypeNativeListTestSafe(NativeList valueToTest) - { - var writeSize = FastBufferWriter.GetWriteSize(valueToTest); - var writer = new FastBufferWriter(writeSize + 2, Allocator.Temp); - using (writer) - { - - Assert.AreEqual(sizeof(int) + sizeof(T) * valueToTest.Length, writeSize); - - RunMethod(nameof(FastBufferWriter.WriteValueSafe), writer, valueToTest); - VerifyPositionAndLength(writer, writeSize); - - WriteCheckBytes(writer, writeSize); - - VerifyArrayEquality(valueToTest, writer.GetUnsafePtr(), 0); - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, writeSize); - } - } -#endif - - [Test, Description("Tests")] - public void WhenWritingUnmanagedType_ValueIsWrittenCorrectly( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseTypeTest(testType, writeType); - } - - [Test] - public void WhenWritingArrayOfUnmanagedElementType_ArrayIsWrittenCorrectly( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseArrayTypeTest(testType, writeType); - } - - [Test] - public void WhenWritingNativeArrayOfUnmanagedElementType_NativeArrayIsWrittenCorrectly( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseNativeArrayTypeTest(testType, writeType); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [Test] - public void WhenWritingNativeListOfUnmanagedElementType_NativeListIsWrittenCorrectly( - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(TestStruct))] - Type testType, - [Values] WriteType writeType) - { - BaseNativeListTypeTest(testType, writeType); - } -#endif - - [TestCase(false, WriteType.WriteDirect)] - [TestCase(false, WriteType.WriteSafe)] - [TestCase(true, WriteType.WriteDirect)] - [TestCase(true, WriteType.WriteSafe)] - public unsafe void WhenWritingString_ValueIsWrittenCorrectly(bool oneByteChars, WriteType writeType) - { - string valueToTest = "Hello, I am a test string!"; - - var serializedValueSize = FastBufferWriter.GetWriteSize(valueToTest, oneByteChars); - - var writer = new FastBufferWriter(serializedValueSize + 3, Allocator.Temp); - using (writer) - { - var offset = 0; - switch (writeType) - { - case WriteType.WriteDirect: - Assert.IsTrue(writer.TryBeginWrite(serializedValueSize + 2), "Writer denied write permission"); - writer.WriteValue(valueToTest, oneByteChars); - break; - case WriteType.WriteSafe: - writer.WriteValueSafe(valueToTest, oneByteChars); - break; - - } - - VerifyPositionAndLength(writer, serializedValueSize + offset); - WriteCheckBytes(writer, serializedValueSize + offset); - - int* sizeValue = (int*)(writer.GetUnsafePtr() + offset); - Assert.AreEqual(valueToTest.Length, *sizeValue); - - fixed (char* asCharPointer = valueToTest) - { - if (oneByteChars) - { - byte* underlyingByteArray = writer.GetUnsafePtr() + sizeof(int) + offset; - for (var i = 0; i < valueToTest.Length; ++i) - { - Assert.AreEqual((byte)asCharPointer[i], underlyingByteArray[i]); - } - - } - else - { - char* underlyingCharArray = (char*)(writer.GetUnsafePtr() + sizeof(int) + offset); - for (var i = 0; i < valueToTest.Length; ++i) - { - Assert.AreEqual(asCharPointer[i], underlyingCharArray[i]); - } - } - } - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, serializedValueSize + offset); - } - } - - public unsafe void RunFixedStringTest(T fixedStringValue, int numBytesWritten, WriteType writeType) where T : unmanaged, INativeList, IUTF8Bytes - { - fixedStringValue.Length = numBytesWritten; - - var serializedValueSize = FastBufferWriter.GetWriteSize(fixedStringValue); - - Assert.AreEqual(fixedStringValue.Length + sizeof(int), serializedValueSize); - - var writer = new FastBufferWriter(serializedValueSize + 3, Allocator.Temp); - using (writer) - { - var offset = 0; - switch (writeType) - { - case WriteType.WriteDirect: - Assert.IsTrue(writer.TryBeginWrite(serializedValueSize + 2), "Writer denied write permission"); - writer.WriteValue(fixedStringValue); - break; - case WriteType.WriteSafe: - writer.WriteValueSafe(fixedStringValue); - break; - - } - - VerifyPositionAndLength(writer, serializedValueSize + offset); - WriteCheckBytes(writer, serializedValueSize + offset); - - int* sizeValue = (int*)(writer.GetUnsafePtr() + offset); - Assert.AreEqual(fixedStringValue.Length, *sizeValue); - - byte* underlyingByteArray = writer.GetUnsafePtr() + sizeof(int) + offset; - for (var i = 0; i < fixedStringValue.Length; ++i) - { - Assert.AreEqual(fixedStringValue[i], underlyingByteArray[i]); - } - - var underlyingArray = writer.ToArray(); - VerifyCheckBytes(underlyingArray, serializedValueSize + offset); - } - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - public void WhenWritingFixedString32Bytes_ValueIsWrittenCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 29; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString32Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - public void WhenWritingFixedString64Bytes_ValueIsWrittenCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 61; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString64Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - public void WhenWritingFixedString128Bytes_ValueIsWrittenCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 125; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString128Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - [TestCase(509, WriteType.WriteSafe)] - public void WhenWritingFixedString512Bytes_ValueIsWrittenCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 509; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString512Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(3, WriteType.WriteDirect)] - [TestCase(5, WriteType.WriteSafe)] - [TestCase(16, WriteType.WriteDirect)] - [TestCase(29, WriteType.WriteSafe)] - [TestCase(61, WriteType.WriteSafe)] - [TestCase(125, WriteType.WriteSafe)] - [TestCase(509, WriteType.WriteSafe)] - [TestCase(4093, WriteType.WriteSafe)] - public void WhenWritingFixedString4096Bytes_ValueIsWrittenCorrectly(int numBytesWritten, WriteType writeType) - { - // Repeats 01234567890123456789... - string valueToTest = ""; - for (var i = 0; i < 4093; ++i) - { - valueToTest += (i % 10).ToString(); - } - - var fixedStringValue = new FixedString4096Bytes(valueToTest); - - RunFixedStringTest(fixedStringValue, numBytesWritten, writeType); - } - - [TestCase(1, 0)] - [TestCase(2, 0)] - [TestCase(3, 0)] - [TestCase(4, 0)] - [TestCase(5, 0)] - [TestCase(6, 0)] - [TestCase(7, 0)] - [TestCase(8, 0)] - - [TestCase(1, 1)] - [TestCase(2, 1)] - [TestCase(3, 1)] - [TestCase(4, 1)] - [TestCase(5, 1)] - [TestCase(6, 1)] - [TestCase(7, 1)] - - [TestCase(1, 2)] - [TestCase(2, 2)] - [TestCase(3, 2)] - [TestCase(4, 2)] - [TestCase(5, 2)] - [TestCase(6, 2)] - - [TestCase(1, 3)] - [TestCase(2, 3)] - [TestCase(3, 3)] - [TestCase(4, 3)] - [TestCase(5, 3)] - - [TestCase(1, 4)] - [TestCase(2, 4)] - [TestCase(3, 4)] - [TestCase(4, 4)] - - [TestCase(1, 5)] - [TestCase(2, 5)] - [TestCase(3, 5)] - - [TestCase(1, 6)] - [TestCase(2, 6)] - - [TestCase(1, 7)] - public unsafe void WhenWritingPartialValueWithCountAndOffset_ValueIsWrittenCorrectly(int count, int offset) - { - var random = new Random(); - var valueToTest = ((ulong)random.Next() << 32) + (ulong)random.Next(); - var writer = new FastBufferWriter(sizeof(ulong) + 2, Allocator.Temp); - using (writer) - { - - Assert.IsTrue(writer.TryBeginWrite(count + 2), "Writer denied write permission"); - writer.WritePartialValue(valueToTest, count, offset); - - var failMessage = $"TestWritingPartialValues failed with value {valueToTest}"; - VerifyPositionAndLength(writer, count, failMessage); - WriteCheckBytes(writer, count, failMessage); - var underlyingArray = writer.ToArray(); - VerifyBytewiseEquality(valueToTest, underlyingArray, offset, 0, count, failMessage); - VerifyCheckBytes(underlyingArray, count, failMessage); - - ulong mask = 0; - for (var i = 0; i < count; ++i) - { - mask = (mask << 8) | 0b11111111; - } - - ulong* checkValue = (ulong*)writer.GetUnsafePtr(); - Assert.AreEqual((valueToTest >> (offset * 8)) & mask, *checkValue & mask); - } - } - - [Test] - public void WhenCallingToArray_ReturnedArrayContainsCorrectData() - { - var testStruct = GetTestStruct(); - var requiredSize = FastBufferWriter.GetWriteSize(testStruct); - var writer = new FastBufferWriter(requiredSize, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(requiredSize); - writer.WriteValue(testStruct); - var array = writer.ToArray(); - var underlyingArray = writer.ToArray(); - for (var i = 0; i < array.Length; ++i) - { - Assert.AreEqual(array[i], underlyingArray[i]); - } - } - } - - [Test] - public void WhenCallingWriteByteWithoutCallingTryBeingWriteFirst_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - Assert.Throws(() => { writer.WriteByte(1); }); - } - } - - [Test] - public void WhenCallingWriteBytesWithoutCallingTryBeingWriteFirst_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - var bytes = new byte[] { 0, 1, 2 }; - Assert.Throws(() => { writer.WriteBytes(bytes, bytes.Length); }); - } - } - - [Test] - public void WhenCallingWriteValueWithUnmanagedTypeWithoutCallingTryBeingWriteFirst_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - int i = 1; - Assert.Throws(() => { writer.WriteValue(i); }); - } - } - - [Test] - public void WhenCallingWriteValueWithByteArrayWithoutCallingTryBeingWriteFirst_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - var bytes = new byte[] { 0, 1, 2 }; - Assert.Throws(() => { writer.WriteValue(bytes); }); - } - } - - [Test] - public void WhenCallingWriteValueWithStringWithoutCallingTryBeingWriteFirst_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - Assert.Throws(() => { writer.WriteValue(""); }); - } - } - - [Test] - public void WhenCallingWriteValueAfterCallingTryBeginWriteWithTooFewBytes_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - int i = 0; - writer.TryBeginWrite(sizeof(int) - 1); - Assert.Throws(() => { writer.WriteValue(i); }); - } - } - - [Test] - public void WhenCallingWriteBytePastBoundaryMarkedByTryBeginWrite_OverflowExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(sizeof(int) - 1); - writer.WriteByte(1); - writer.WriteByte(2); - writer.WriteByte(3); - Assert.Throws(() => { writer.WriteByte(4); }); - } - } - - [Test] - public void WhenCallingWriteByteDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteByte(1); }); - } - } - - [Test] - public void WhenCallingWriteBytesDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteBytes(bytes, bytes.Length); }); - } - } - - [Test] - public void WhenCallingWriteValueWithUnmanagedTypeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - int i = 1; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteValue(i); }); - } - } - - [Test] - public void WhenCallingWriteValueWithByteArrayDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteBytes(bytes, bytes.Length); }); - } - } - - [Test] - public void WhenCallingWriteValueWithStringDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteValue(""); }); - } - } - - [Test] - public void WhenCallingWriteByteSafeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteByteSafe(1); }); - } - } - - [Test] - public void WhenCallingWriteBytesSafeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteBytesSafe(bytes, bytes.Length); }); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithUnmanagedTypeDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - int i = 1; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteValueSafe(i); }); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithByteArrayDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteBytesSafe(bytes, bytes.Length); }); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithStringDuringBitwiseContext_InvalidOperationExceptionIsThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using var context = writer.EnterBitwiseContext(); - Assert.Throws(() => { writer.WriteValueSafe(""); }); - } - } - - [Test] - public void WhenCallingWriteByteAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteByte(1); - } - } - - [Test] - public void WhenCallingWriteBytesAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteBytes(bytes, bytes.Length); - } - } - - [Test] - public void WhenCallingWriteValueWithUnmanagedTypeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - int i = 1; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValue(i); - } - } - - [Test] - public void WhenCallingWriteValueWithByteArrayAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValue(bytes); - } - } - - [Test] - public void WhenCallingWriteValueWithStringAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValue(""); - } - } - - [Test] - public void WhenCallingWriteByteSafeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteByteSafe(1); - } - } - - [Test] - public void WhenCallingWriteBytesSafeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteBytesSafe(bytes, bytes.Length); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithUnmanagedTypeAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - int i = 1; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValueSafe(i); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithByteArrayAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - var bytes = new byte[] { 0, 1, 2 }; - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValueSafe(bytes); - } - } - - [Test] - public void WhenCallingWriteValueSafeWithStringAfterExitingBitwiseContext_InvalidOperationExceptionIsNotThrown() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - - using (writer) - { - writer.TryBeginWrite(100); - using (var context = writer.EnterBitwiseContext()) - { - context.WriteBit(true); - } - writer.WriteValueSafe(""); - } - } - - [Test] - public void WhenCallingTryBeginWrite_TheAllowedWritePositionIsMarkedRelativeToCurrentPosition() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(100); - writer.WriteByte(1); - writer.TryBeginWrite(1); - writer.WriteByte(1); - Assert.Throws(() => { writer.WriteByte(1); }); - } - } - - [Test] - public void WhenWritingAfterSeeking_TheNewWriteGoesToTheCorrectPosition() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.Seek(5); - writer.WriteByteSafe(0); - Assert.AreEqual(writer.Position, 6); - - writer.Seek(0); - writer.WriteByteSafe(1); - Assert.AreEqual(writer.Position, 1); - - writer.Seek(10); - Assert.AreEqual(writer.Position, 10); - - writer.Seek(2); - writer.WriteByteSafe(2); - - writer.Seek(1); - writer.WriteByteSafe(3); - - writer.Seek(4); - writer.WriteByteSafe(4); - - writer.Seek(3); - writer.WriteByteSafe(5); - - Assert.AreEqual(writer.Position, 4); - - var expected = new byte[] { 1, 3, 2, 5, 4, 0 }; - var underlyingArray = writer.ToArray(); - for (var i = 0; i < expected.Length; ++i) - { - Assert.AreEqual(expected[i], underlyingArray[i]); - } - } - } - - [Test] - public void WhenSeekingForward_LengthUpdatesToNewPosition() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - Assert.AreEqual(writer.Length, 0); - writer.Seek(5); - Assert.AreEqual(writer.Length, 5); - writer.Seek(10); - Assert.AreEqual(writer.Length, 10); - } - } - - [Test] - public void WhenSeekingBackward_LengthDoesNotChange() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - Assert.AreEqual(writer.Length, 0); - writer.Seek(5); - Assert.AreEqual(writer.Length, 5); - writer.Seek(0); - Assert.AreEqual(writer.Length, 5); - } - } - - [Test] - public void WhenTruncatingToSpecificPositionAheadOfWritePosition_LengthIsUpdatedAndPositionIsNot() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.Seek(10); - Assert.AreEqual(writer.Position, 10); - Assert.AreEqual(writer.Length, 10); - - writer.Seek(5); - Assert.AreEqual(writer.Position, 5); - Assert.AreEqual(writer.Length, 10); - - writer.Truncate(8); - Assert.AreEqual(writer.Position, 5); - Assert.AreEqual(writer.Length, 8); - } - } - - [Test] - public void WhenTruncatingToSpecificPositionBehindWritePosition_BothLengthAndPositionAreUpdated() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.Seek(10); - Assert.AreEqual(writer.Position, 10); - Assert.AreEqual(writer.Length, 10); - - writer.Truncate(8); - Assert.AreEqual(writer.Position, 8); - Assert.AreEqual(writer.Length, 8); - } - } - - [Test] - public void WhenTruncatingToCurrentPosition_LengthIsUpdated() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.Seek(10); - Assert.AreEqual(writer.Position, 10); - Assert.AreEqual(writer.Length, 10); - - writer.Seek(5); - writer.Truncate(); - Assert.AreEqual(writer.Position, 5); - Assert.AreEqual(writer.Length, 5); - } - } - - [Test] - public void WhenCreatingNewFastBufferWriter_CapacityIsCorrect() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - Assert.AreEqual(100, writer.Capacity); - writer.Dispose(); - - writer = new FastBufferWriter(200, Allocator.Temp); - Assert.AreEqual(200, writer.Capacity); - writer.Dispose(); - } - - [Test] - public void WhenCreatingNewFastBufferWriter_MaxCapacityIsCorrect() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - Assert.AreEqual(100, writer.MaxCapacity); - writer.Dispose(); - - writer = new FastBufferWriter(100, Allocator.Temp, 200); - Assert.AreEqual(200, writer.MaxCapacity); - writer.Dispose(); - } - - [Test] - public void WhenCreatingNewFastBufferWriter_IsInitializedIsTrue() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - Assert.AreEqual(true, writer.IsInitialized); - writer.Dispose(); - } - - [Test] - public void WhenDisposingFastBufferWriter_IsInitializedIsFalse() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - writer.Dispose(); - Assert.AreEqual(false, writer.IsInitialized); - } - - [Test] - public void WhenUsingDefaultFastBufferWriter_IsInitializedIsFalse() - { - FastBufferWriter writer = default; - Assert.AreEqual(false, writer.IsInitialized); - } - - [Test] - public void WhenRequestingWritePastBoundsForNonGrowingWriter_TryBeginWriteReturnsFalse() - { - var writer = new FastBufferWriter(150, Allocator.Temp); - using (writer) - { - var testStruct = GetTestStruct(); - writer.TryBeginWriteValue(testStruct); - writer.WriteValue(testStruct); - - // Seek to exactly where the write would cross the buffer boundary - writer.Seek(150 - FastBufferWriter.GetWriteSize(testStruct) + 1); - - // Writer isn't allowed to grow because it didn't specify a maxSize - Assert.IsFalse(writer.TryBeginWriteValue(testStruct)); - } - } - - [Test] - public void WhenTryBeginWriteReturnsFalse_WritingThrowsOverflowException() - { - var writer = new FastBufferWriter(150, Allocator.Temp); - using (writer) - { - var testStruct = GetTestStruct(); - writer.TryBeginWriteValue(testStruct); - writer.WriteValue(testStruct); - - // Seek to exactly where the write would cross the buffer boundary - writer.Seek(150 - FastBufferWriter.GetWriteSize(testStruct) + 1); - - // Writer isn't allowed to grow because it didn't specify a maxSize - Assert.IsFalse(writer.TryBeginWriteValue(testStruct)); - Assert.Throws(() => writer.WriteValue(testStruct)); - } - } - - [Test] - public void WhenTryBeginWriteReturnsFalseAndOverflowExceptionIsThrown_DataIsNotAffected() - { - var writer = new FastBufferWriter(150, Allocator.Temp); - using (writer) - { - var testStruct = GetTestStruct(); - writer.TryBeginWriteValue(testStruct); - writer.WriteValue(testStruct); - - // Seek to exactly where the write would cross the buffer boundary - writer.Seek(150 - FastBufferWriter.GetWriteSize(testStruct) + 1); - - // Writer isn't allowed to grow because it didn't specify a maxSize - Assert.IsFalse(writer.TryBeginWriteValue(testStruct)); - Assert.Throws(() => writer.WriteValue(testStruct)); - VerifyBytewiseEquality(testStruct, writer.ToArray(), 0, 0, FastBufferWriter.GetWriteSize(testStruct)); - } - } - - [Test] - public void WhenRequestingWritePastBoundsForGrowingWriter_BufferGrowsWithoutLosingData() - { - var growingWriter = new FastBufferWriter(150, Allocator.Temp, 500); - using (growingWriter) - { - var testStruct = GetTestStruct(); - growingWriter.TryBeginWriteValue(testStruct); - growingWriter.WriteValue(testStruct); - - // Seek to exactly where the write would cross the buffer boundary - growingWriter.Seek(150 - FastBufferWriter.GetWriteSize(testStruct) + 1); - - Assert.IsTrue(growingWriter.TryBeginWriteValue(testStruct)); - - // Growth doubles the size - Assert.AreEqual(300, growingWriter.Capacity); - Assert.AreEqual(growingWriter.Position, 150 - FastBufferWriter.GetWriteSize(testStruct) + 1); - growingWriter.WriteValue(testStruct); - - // Verify the growth properly copied the existing data - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 0, FastBufferWriter.GetWriteSize(testStruct)); - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 150 - FastBufferWriter.GetWriteSize(testStruct) + 1, FastBufferWriter.GetWriteSize(testStruct)); - } - } - - [Test] - public void WhenRequestingWriteExactlyAtBoundsForGrowingWriter_BufferDoesntGrow() - { - var growingWriter = new FastBufferWriter(300, Allocator.Temp, 500); - using (growingWriter) - { - var testStruct = GetTestStruct(); - growingWriter.TryBeginWriteValue(testStruct); - growingWriter.WriteValue(testStruct); - - growingWriter.Seek(300 - FastBufferWriter.GetWriteSize(testStruct)); - Assert.IsTrue(growingWriter.TryBeginWriteValue(testStruct)); - Assert.AreEqual(300, growingWriter.Capacity); - Assert.AreEqual(growingWriter.Position, growingWriter.ToArray().Length); - growingWriter.WriteValue(testStruct); - Assert.AreEqual(300, growingWriter.Position); - - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 0, FastBufferWriter.GetWriteSize(testStruct)); - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 300 - FastBufferWriter.GetWriteSize(testStruct), FastBufferWriter.GetWriteSize(testStruct)); - } - } - - [Test] - public void WhenBufferGrows_MaxCapacityIsNotExceeded() - { - var growingWriter = new FastBufferWriter(300, Allocator.Temp, 500); - using (growingWriter) - { - var testStruct = GetTestStruct(); - growingWriter.TryBeginWriteValue(testStruct); - growingWriter.WriteValue(testStruct); - - growingWriter.Seek(300); - Assert.IsTrue(growingWriter.TryBeginWriteValue(testStruct)); - - Assert.AreEqual(500, growingWriter.Capacity); - Assert.AreEqual(growingWriter.Position, 300); - - growingWriter.WriteValue(testStruct); - - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 0, FastBufferWriter.GetWriteSize(testStruct)); - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 300, FastBufferWriter.GetWriteSize(testStruct)); - } - } - - [Test] - public void WhenBufferGrowthRequiredIsMoreThanDouble_BufferGrowsEnoughToContainRequestedValue() - { - var growingWriter = new FastBufferWriter(1, Allocator.Temp, 500); - using (growingWriter) - { - var testStruct = GetTestStruct(); - Assert.IsTrue(growingWriter.TryBeginWriteValue(testStruct)); - - // Buffer size doubles with each growth, so since we're starting with a size of 1, that means - // the resulting size should be the next power of 2 above the size of testStruct. - Assert.AreEqual(Math.Pow(2, Math.Ceiling(Mathf.Log(FastBufferWriter.GetWriteSize(testStruct), 2))), - growingWriter.Capacity); - Assert.AreEqual(growingWriter.Position, 0); - - growingWriter.WriteValue(testStruct); - - VerifyBytewiseEquality(testStruct, growingWriter.ToArray(), 0, 0, FastBufferWriter.GetWriteSize(testStruct)); - } - } - - [Test] - public void WhenTryingToWritePastMaxCapacity_GrowthDoesNotOccurAndTryBeginWriteReturnsFalse() - { - var growingWriter = new FastBufferWriter(300, Allocator.Temp, 500); - using (growingWriter) - { - Assert.IsFalse(growingWriter.TryBeginWrite(501)); - - Assert.AreEqual(300, growingWriter.Capacity); - Assert.AreEqual(growingWriter.Position, 0); - } - } - - [Test] - public unsafe void WhenCallingTryBeginWriteInternal_AllowedWritePositionDoesNotMoveBackward() - { - var writer = new FastBufferWriter(100, Allocator.Temp); - using (writer) - { - writer.TryBeginWrite(25); - writer.TryBeginWriteInternal(5); - Assert.AreEqual(writer.Handle->AllowedWriteMark, 25); - } - } - } -} diff --git a/Tests/Editor/Serialization/FastBufferWriterTests.cs.meta b/Tests/Editor/Serialization/FastBufferWriterTests.cs.meta deleted file mode 100644 index b549311..0000000 --- a/Tests/Editor/Serialization/FastBufferWriterTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1cef42b60935e29469ed1404fb30ba2d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs b/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs deleted file mode 100644 index f279f4d..0000000 --- a/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs +++ /dev/null @@ -1,95 +0,0 @@ -using NUnit.Framework; -using Unity.Collections; - -namespace Unity.Netcode.EditorTests -{ - internal class UserBitReaderAndBitWriterTests_NCCBUG175 - { - - [Test] - public void WhenBitwiseWritingMoreThan8Bits_ValuesAreCorrect() - { - using var writer = new FastBufferWriter(1024, Allocator.Temp); - ulong inVal = 123456789; - - for (int i = 0; i < 100; ++i) - { - writer.WriteValueSafe(i); - } - - using (var bitWriter = writer.EnterBitwiseContext()) - { - for (int i = 0; i < 16; ++i) - { - Assert.IsTrue((bitWriter.TryBeginWriteBits(32))); - bitWriter.WriteBits(inVal, 31); - bitWriter.WriteBit(true); - } - } - - using var reader = new FastBufferReader(writer, Allocator.Temp); - - for (int i = 0; i < 100; ++i) - { - reader.ReadValueSafe(out int outVal); - Assert.AreEqual(i, outVal); - } - - using var bitReader = reader.EnterBitwiseContext(); - for (int i = 0; i < 16; ++i) - { - Assert.IsTrue(bitReader.TryBeginReadBits(32)); - bitReader.ReadBits(out ulong outVal, 31); - bitReader.ReadBit(out bool bit); - Assert.AreEqual(inVal, outVal); - Assert.AreEqual(true, bit); - } - } - - [Test] - public void WhenBitwiseReadingMoreThan8Bits_ValuesAreCorrect() - { - using var writer = new FastBufferWriter(1024, Allocator.Temp); - ulong inVal = 123456789; - - for (int i = 0; i < 100; ++i) - { - writer.WriteValueSafe(i); - } - - uint combined = (uint)inVal | (1u << 31); - writer.WriteValueSafe(combined); - writer.WriteValueSafe(combined); - writer.WriteValueSafe(combined); - - using var reader = new FastBufferReader(writer, Allocator.Temp); - - for (int i = 0; i < 100; ++i) - { - reader.ReadValueSafe(out int outVal); - Assert.AreEqual(i, outVal); - } - - using (var bitReader = reader.EnterBitwiseContext()) - { - Assert.IsTrue(bitReader.TryBeginReadBits(32)); - bitReader.ReadBits(out ulong outVal, 31); - bitReader.ReadBit(out bool bit); - Assert.AreEqual(inVal, outVal); - Assert.AreEqual(true, bit); - - Assert.IsTrue(bitReader.TryBeginReadBits(32)); - bitReader.ReadBits(out outVal, 31); - bitReader.ReadBit(out bit); - Assert.AreEqual(inVal, outVal); - Assert.AreEqual(true, bit); - - Assert.IsTrue(bitReader.TryBeginReadBits(32)); - bitReader.ReadBits(out outVal, 31); - bitReader.ReadBit(out bit); - Assert.AreEqual(inVal, outVal); - Assert.AreEqual(true, bit); - } - } - } -} diff --git a/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs.meta b/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs.meta deleted file mode 100644 index b1a34e7..0000000 --- a/Tests/Editor/Serialization/UserBitReaderAndBitWriterTests_NCCBUG175.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: adfa622d42824b70a39a30b6aa22c9c5 -timeCreated: 1660758428 \ No newline at end of file diff --git a/Tests/Editor/Timing.meta b/Tests/Editor/Timing.meta deleted file mode 100644 index 6a21bd9..0000000 --- a/Tests/Editor/Timing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ff3d73d1a9b7596419b0f389d0219f31 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs b/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs deleted file mode 100644 index 275e891..0000000 --- a/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.EditorTests -{ - /// - /// Tests for running a as a client. - /// - internal class ClientNetworkTimeSystemTests - { - private const double k_AcceptableRttOffset = 0.03d; // 30ms offset is fine - - /// - /// Tests whether time is stable if RTT is stable. - /// - [Test] - public void StableRttTest() - { - double receivedServerTime = 2; - - var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, 0.1d); - timeSystem.Reset(receivedServerTime, 0.15); - var tickSystem = new NetworkTickSystem(60, timeSystem.LocalTime, timeSystem.ServerTime); - - Assert.True(timeSystem.LocalTime > 2); - - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, 0.095f, 0.105f, 42); // 10ms jitter - - // run for a while so that we reach regular RTT offset - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps[step]); - }); - - // check how we close we are to target time. - var expectedRtt = 0.1d; - var offsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; - Debug.Log($"offset to target time after running for a while: {offsetToTarget}"); - Assert.IsTrue(Math.Abs(offsetToTarget) < k_AcceptableRttOffset); - - // run again, test that we never need to speed up or slow down under stable RTT - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps[step]); - }); - - // check again to ensure we are still close to the target - var newOffsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; - Debug.Log($"offset to target time after running longer: {newOffsetToTarget}"); - Assert.IsTrue(Math.Abs(newOffsetToTarget) < k_AcceptableRttOffset); - - // difference between first and second offset should be minimal - var dif = offsetToTarget - newOffsetToTarget; - Assert.IsTrue(Math.Abs(dif) < 0.01d); // less than 10ms - } - - /// - /// Tests whether local time can speed up and slow down to catch up when RTT changes. - /// - [Test] - public void RttCatchupSlowdownTest() - { - double receivedServerTime = 2; - - var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, 0.1d); - timeSystem.Reset(receivedServerTime, 0.15); - var tickSystem = new NetworkTickSystem(60, timeSystem.LocalTime, timeSystem.ServerTime); - - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, 0.095f, 0.105f, 42); // 10ms jitter - - // run for a while so that we reach regular RTT offset - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps[step]); - }); - - // increase RTT to ~200ms from ~100ms - var rttSteps2 = TimingTestHelper.GetRandomTimeSteps(1000f, 0.195f, 0.205f, 42); - - double unscaledLocalTime = timeSystem.LocalTime; - double unscaledServerTime = timeSystem.ServerTime; - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - unscaledLocalTime += steps[step]; - unscaledServerTime += steps[step]; - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps2[step]); - }); - - var totalLocalSpeedUpTime = timeSystem.LocalTime - unscaledLocalTime; - var totalServerSpeedUpTime = timeSystem.ServerTime - unscaledServerTime; - - // speed up of 0.1f expected - Debug.Log($"Total local speed up time catch up: {totalLocalSpeedUpTime}"); - Assert.True(Math.Abs(totalLocalSpeedUpTime - 0.1) < k_AcceptableRttOffset); - Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset); // server speedup/slowdowns should not be affected by RTT - - - // run again with RTT ~100ms and see whether we slow down by -0.1f - unscaledLocalTime = timeSystem.LocalTime; - unscaledServerTime = timeSystem.ServerTime; - - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - unscaledLocalTime += steps[step]; - unscaledServerTime += steps[step]; - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps[step]); - }); - - totalLocalSpeedUpTime = timeSystem.LocalTime - unscaledLocalTime; - totalServerSpeedUpTime = timeSystem.ServerTime - unscaledServerTime; - - // slow down of 0.1f expected - Debug.Log($"Total local speed up time slow down: {totalLocalSpeedUpTime}"); - Assert.True(Math.Abs(totalLocalSpeedUpTime + 0.1) < k_AcceptableRttOffset); - Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset); // server speedup/slowdowns should not be affected by RTT - - - } - - /// - /// Tests whether time resets when there is a huge spike in RTT and is able to stabilize again. - /// - [Test] - public void ResetTest() - { - double receivedServerTime = 2; - - var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, 0.1d); - timeSystem.Reset(receivedServerTime, 0.15); - var tickSystem = new NetworkTickSystem(60, timeSystem.LocalTime, timeSystem.ServerTime); - - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, 0.095f, 0.105f, 42); // 10ms jitter - - // run for a while so that we reach regular RTT offset - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) - { - // sync network stats - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps[step]); - }); - - - // increase RTT to ~500ms from ~100ms - var rttSteps2 = TimingTestHelper.GetRandomTimeSteps(1000f, 0.495f, 0.505f, 42); - - // run a single advance expect a hard rest - - receivedServerTime += 1 / 60d; - timeSystem.Sync(receivedServerTime, 0.5); - bool reset = timeSystem.Advance(1 / 60d); - Assert.IsTrue(reset); - - TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step, bool reset) - { - Assert.IsFalse(reset); - - // sync network stats - receivedServerTime += steps[step]; - timeSystem.Sync(receivedServerTime, rttSteps2[step]); - - // after hard reset time should stay close to rtt - var expectedRtt = 0.5d; - Assert.IsTrue(Math.Abs((timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec) < k_AcceptableRttOffset); - - }); - } - } -} diff --git a/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs.meta b/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs.meta deleted file mode 100644 index 4d2ab78..0000000 --- a/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1cd95d37c9e3f904ba19b1fcf33123c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Timing/NetworkTimeTests.cs b/Tests/Editor/Timing/NetworkTimeTests.cs deleted file mode 100644 index 2a137bd..0000000 --- a/Tests/Editor/Timing/NetworkTimeTests.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - internal class NetworkTimeTests - { - [Test] - [TestCase(0d, 0u)] - [TestCase(5d, 0u)] - [TestCase(-5d, 0u)] - public void TestFailCreateInvalidTime(double time, uint tickrate) - { - Assert.Throws(() => new NetworkTime(tickrate, time)); - } - - [Test] - [TestCase(0d, 0f, 20u)] - [TestCase(0d, 0f, 30u)] - [TestCase(0d, 0f, 60u)] - [TestCase(201d, 201f, 20u)] - [TestCase(201d, 201f, 30u)] - [TestCase(201d, 201f, 60u)] - [TestCase(-4301d, -4301f, 20u)] - [TestCase(-4301d, -4301f, 30u)] - [TestCase(-4301d, -4301f, 60u)] - [TestCase(float.MaxValue, float.MaxValue, 20u)] - [TestCase(float.MaxValue, float.MaxValue, 30u)] - [TestCase(float.MaxValue, float.MaxValue, 60u)] - public void TestTimeAsFloat(double d, float f, uint tickRate) - { - var networkTime = new NetworkTime(tickRate, d); - Assert.True(Mathf.Approximately(networkTime.TimeAsFloat, f)); - } - - [Test] - [TestCase(53.55d, 53.5d, 10u)] - [TestCase(1013553.55d, 1013553.5d, 10u)] - [TestCase(0d, 0d, 10u)] - [TestCase(-27.41d, -27.5d, 10u)] - [TestCase(53.55d, 53.54d, 50u)] - [TestCase(1013553.55d, 1013553.54d, 50u)] - [TestCase(0d, 0d, 50u)] - [TestCase(-27.4133d, -27.42d, 50u)] - public void TestToFixedTime(double time, double expectedFixedTime, uint tickRate) - { - Assert.AreEqual(expectedFixedTime, new NetworkTime(tickRate, time).ToFixedTime().Time); - } - - [Test] - [TestCase(34d, 0)] - [TestCase(17.32d, 0.2d / 60d)] - [TestCase(-42.44d, 1d / 60d - 0.4d / 60d)] - [TestCase(-6d, 0)] - [TestCase(int.MaxValue / 61d, 0.00082, 10d)] // Int.Max / 61 / (1/60) to get divisor then: Int.Max - divisor * 1 / 60 - public void NetworkTimeCreate(double time, double tickOffset, double epsilon = 0.0001d) - { - var networkTime = new NetworkTime(60, time); - - Assert.IsTrue(Approximately(time, networkTime.Time)); - Assert.IsTrue(Approximately(networkTime.Tick * networkTime.FixedDeltaTime + networkTime.TickOffset, networkTime.Time, epsilon)); - Assert.IsTrue(Approximately(networkTime.TickOffset, tickOffset)); - } - - [Test] - public void NetworkTimeDefault() - { - NetworkTime defaultTime = default; - - Assert.IsTrue(defaultTime.Time == 0f); - } - - [Test] - [TestCase(17.32d)] - [TestCase(34d)] - [TestCase(-42.4d)] - [TestCase(-6d)] - [TestCase(int.MaxValue / 61d)] - public void NetworkTimeAddFloatTest(double time) - { - double a = 34d; - double floatResultB = a + time; - - var timeA = new NetworkTime(60, a); - NetworkTime timeB = timeA + time; - - Assert.IsTrue(Approximately(floatResultB, timeB.Time)); - } - - [Test] - [TestCase(17.32d)] - [TestCase(34d)] - [TestCase(-42.4d)] - [TestCase(-6d)] - [TestCase(int.MaxValue / 61d)] - public void NetworkTimeSubFloatTest(double time) - { - double a = 34d; - double floatResultB = a - time; - - var timeA = new NetworkTime(60, a); - NetworkTime timeB = timeA - time; - - Assert.IsTrue(Approximately(floatResultB, timeB.Time)); - } - - [Test] - [TestCase(17.32d)] - [TestCase(34d)] - [TestCase(-42.4d)] - [TestCase(-6d)] - [TestCase(int.MaxValue / 61d)] - public void NetworkTimeAddNetworkTimeTest(double time) - { - double a = 34d; - double floatResultB = a + time; - - var timeA = new NetworkTime(60, a); - NetworkTime timeB = timeA + new NetworkTime(60, time); - Assert.IsTrue(Approximately(floatResultB, timeB.Time)); - } - - [Test] - [TestCase(17.32d)] - [TestCase(34d)] - [TestCase(-42.4d)] - [TestCase(-6d)] - [TestCase(int.MaxValue / 61d)] - public void NetworkTimeSubNetworkTimeTest(double time) - { - double a = 34d; - - double floatResultB = a - time; - - var timeA = new NetworkTime(60, a); - NetworkTime timeB = timeA - new NetworkTime(60, time); - Assert.IsTrue(Approximately(floatResultB, timeB.Time)); - } - - [Test] - public void NetworkTimeAdvanceTest() - { - var random = new Random(42); - var randomSteps = Enumerable.Repeat(0f, 1000).Select(t => Mathf.Lerp(1 / 25f, 1.80f, (float)random.NextDouble())).ToList(); - - NetworkTimeAdvanceTestInternal(randomSteps, 60, 0f); - NetworkTimeAdvanceTestInternal(randomSteps, 1, 0f); - NetworkTimeAdvanceTestInternal(randomSteps, 10, 0f); - NetworkTimeAdvanceTestInternal(randomSteps, 20, 0f); - NetworkTimeAdvanceTestInternal(randomSteps, 30, 0f); - NetworkTimeAdvanceTestInternal(randomSteps, 144, 0f); - - NetworkTimeAdvanceTestInternal(randomSteps, 60, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 1, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 10, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 20, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 30, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 30, 23132.231f); - NetworkTimeAdvanceTestInternal(randomSteps, 144, 23132.231f); - - var shortSteps = Enumerable.Repeat(1 / 30f, 1000); - - NetworkTimeAdvanceTestInternal(shortSteps, 60, 0f); - NetworkTimeAdvanceTestInternal(shortSteps, 1, 0f); - NetworkTimeAdvanceTestInternal(shortSteps, 10, 0f); - NetworkTimeAdvanceTestInternal(shortSteps, 20, 0f); - NetworkTimeAdvanceTestInternal(shortSteps, 30, 0f); - NetworkTimeAdvanceTestInternal(shortSteps, 144, 0f); - - NetworkTimeAdvanceTestInternal(shortSteps, 60, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 60, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 1, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 10, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 20, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 30, 1000000f); - NetworkTimeAdvanceTestInternal(shortSteps, 144, 1000000f); - } - - private void NetworkTimeAdvanceTestInternal(IEnumerable steps, uint tickRate, float start, float start2 = 0f) - { - float maxAcceptableTotalOffset = 0.005f; - - var startTime = new NetworkTime(tickRate, start); - var startTime2 = new NetworkTime(tickRate, start2); - NetworkTime dif = startTime2 - startTime; - - foreach (var step in steps) - { - startTime += step; - startTime2 += step; - Assert.IsTrue(Approximately(startTime.Time, (startTime2 - dif).Time)); - } - - Assert.IsTrue(Approximately(startTime.Time, (startTime2 - dif).Time, maxAcceptableTotalOffset)); - } - - [Test] - public void NetworkTickAdvanceTest() - { - var shortSteps = Enumerable.Repeat(1 / 30f, 1000); - NetworkTickAdvanceTestInternal(shortSteps, 30, 0.0f, 0.0f); - } - - private NetworkTickSystem m_TickSystem; - private NetworkTimeSystem m_TimeSystem; - private int m_PreviousTick; - - private void NetworkTickAdvanceTestInternal(IEnumerable steps, uint tickRate, float start, float start2 = 0f) - { - m_PreviousTick = 0; - m_TickSystem = new NetworkTickSystem(tickRate, start, start2); - m_TimeSystem = NetworkTimeSystem.ServerTimeSystem(); - - m_TickSystem.Tick += TickUpdate; - foreach (var step in steps) - { - m_TimeSystem.Advance(step); - m_TickSystem.UpdateTick(m_TimeSystem.LocalTime, m_TimeSystem.ServerTime); - } - } - - private void TickUpdate() - { - // Make sure our tick is precisely 1 + m_PreviousTick - Assert.IsTrue(m_TickSystem.LocalTime.Tick == m_PreviousTick + 1); - // Assign the m_PreviousTick value for next tick check - m_PreviousTick = m_TickSystem.LocalTime.Tick; - } - - private static bool Approximately(double a, double b, double epsilon = 0.000001d) - { - var dif = Math.Abs(a - b); - return dif <= epsilon; - } - } -} diff --git a/Tests/Editor/Timing/NetworkTimeTests.cs.meta b/Tests/Editor/Timing/NetworkTimeTests.cs.meta deleted file mode 100644 index 74e6d2e..0000000 --- a/Tests/Editor/Timing/NetworkTimeTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6c9814eeb95ebba4d8cbb67deab9369b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs b/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs deleted file mode 100644 index 8d5edba..0000000 --- a/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.EditorTests -{ - internal class ServerNetworkTimeSystemTests - { - - /// - /// On the server local time should always be equal to server time. This test ensures that this is the case. - /// - [Test] - public void LocalTimeEqualServerTimeTest() - { - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - - var serverTimeSystem = NetworkTimeSystem.ServerTimeSystem(); - var serverTickSystem = new NetworkTickSystem(60, 0, 0); - - serverTimeSystem.Reset(0.5d, 0); - - TimingTestHelper.ApplySteps(serverTimeSystem, serverTickSystem, steps, step => - { - Assert.IsTrue(Mathf.Approximately((float)serverTimeSystem.LocalTime, (float)serverTimeSystem.ServerTime)); - Assert.IsTrue(Mathf.Approximately((float)serverTickSystem.LocalTime.Time, (float)serverTimeSystem.ServerTime)); - }); - - Assert.IsTrue(serverTimeSystem.LocalTime > 1d); - - } - - } -} - - diff --git a/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs.meta b/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs.meta deleted file mode 100644 index e045dfa..0000000 --- a/Tests/Editor/Timing/ServerNetworkTimeSystemTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 970d8f921595c7249a5ffc92fd74c7fc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Timing/TimingTestHelper.cs b/Tests/Editor/Timing/TimingTestHelper.cs deleted file mode 100644 index e1dee9b..0000000 --- a/Tests/Editor/Timing/TimingTestHelper.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using Random = System.Random; - -namespace Unity.Netcode.EditorTests -{ - /// - /// Helper functions for timing related tests. Allows to get a set of time steps and simulate time advancing without the need of a full playmode test. - /// - internal static class TimingTestHelper - { - public static List GetRandomTimeSteps(float totalDuration, float min, float max, int seed) - { - var random = new Random(seed); - var steps = new List(); - - while (totalDuration > 0f) - { - var next = Mathf.Lerp(min, max, (float)random.NextDouble()); - steps.Add(next); - totalDuration -= next; - } - - // correct overshoot at the end - steps[steps.Count - 1] -= totalDuration; - - return steps; - } - - public delegate void StepCheckDelegate(int step); - - public delegate void StepCheckResetDelegate(int step, bool reset); - - public static void ApplySteps(NetworkTimeSystem timeSystem, NetworkTickSystem tickSystem, List steps, StepCheckDelegate stepCheck = null) - { - for (var i = 0; i < steps.Count; i++) - { - var step = steps[i]; - timeSystem.Advance(step); - tickSystem.UpdateTick(timeSystem.LocalTime, timeSystem.ServerTime); - if (stepCheck != null) - { - stepCheck(i); - } - } - } - - public static void ApplySteps(NetworkTimeSystem timeSystem, NetworkTickSystem tickSystem, List steps, StepCheckResetDelegate stepCheck = null) - { - for (var i = 0; i < steps.Count; i++) - { - var step = steps[i]; - var reset = timeSystem.Advance(step); - tickSystem.UpdateTick(timeSystem.LocalTime, timeSystem.ServerTime); - if (stepCheck != null) - { - stepCheck(i, reset); - } - } - } - } -} - diff --git a/Tests/Editor/Timing/TimingTestHelper.cs.meta b/Tests/Editor/Timing/TimingTestHelper.cs.meta deleted file mode 100644 index a258213..0000000 --- a/Tests/Editor/Timing/TimingTestHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9010f986d5ecb994a8dd34076ff41c8e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Transports.meta b/Tests/Editor/Transports.meta deleted file mode 100644 index 3ec56fb..0000000 --- a/Tests/Editor/Transports.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f4ecf3bb8c5654c1aae7f73d21e8c56e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Transports/BatchedReceiveQueueTests.cs b/Tests/Editor/Transports/BatchedReceiveQueueTests.cs deleted file mode 100644 index fef8a3b..0000000 --- a/Tests/Editor/Transports/BatchedReceiveQueueTests.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.Transports.UTP; -#if !UTP_TRANSPORT_2_0_ABOVE -using Unity.Networking.Transport; -#endif - -namespace Unity.Netcode.EditorTests -{ - internal class BatchedReceiveQueueTests - { - [Test] - public void BatchedReceiveQueue_EmptyReader() - { - var data = new NativeArray(0, Allocator.Temp); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedReceiveQueue_SingleMessage() - { - var dataLength = sizeof(int) + 1; - - var data = new NativeArray(dataLength, Allocator.Temp); - - var writer = new DataStreamWriter(data); - writer.WriteInt(1); - writer.WriteByte(42); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - - Assert.False(q.IsEmpty); - - var message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedReceiveQueue_MultipleMessages() - { - var dataLength = (sizeof(int) + 1) * 2; - - var data = new NativeArray(dataLength, Allocator.Temp); - - var writer = new DataStreamWriter(data); - writer.WriteInt(1); - writer.WriteByte(42); - writer.WriteInt(1); - writer.WriteByte(142); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - - Assert.False(q.IsEmpty); - - var message1 = q.PopMessage(); - Assert.AreEqual(1, message1.Count); - Assert.AreEqual((byte)42, message1.Array[message1.Offset]); - - var message2 = q.PopMessage(); - Assert.AreEqual(1, message2.Count); - Assert.AreEqual((byte)142, message2.Array[message2.Offset]); - - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedReceiveQueue_PartialMessage() - { - var dataLength = sizeof(int); - - var data = new NativeArray(dataLength, Allocator.Temp); - - var writer = new DataStreamWriter(data); - writer.WriteInt(42); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - - Assert.False(q.IsEmpty); - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - } - - [Test] - public void BatchedReceiveQueue_PushReader_ToFilledQueue() - { - var data1Length = sizeof(int); - var data2Length = sizeof(byte); - - var data1 = new NativeArray(data1Length, Allocator.Temp); - var data2 = new NativeArray(data2Length, Allocator.Temp); - - var writer1 = new DataStreamWriter(data1); - writer1.WriteInt(1); - var writer2 = new DataStreamWriter(data2); - writer2.WriteByte(42); - - var reader1 = new DataStreamReader(data1); - var reader2 = new DataStreamReader(data2); - - var q = new BatchedReceiveQueue(reader1); - - Assert.False(q.IsEmpty); - - q.PushReader(reader2); - - Assert.False(q.IsEmpty); - - var message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedReceiveQueue_PushReader_ToPartiallyFilledQueue() - { - var dataLength = sizeof(int) + 1; - - var data = new NativeArray(dataLength, Allocator.Temp); - - var writer = new DataStreamWriter(data); - writer.WriteInt(1); - writer.WriteByte(42); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - - reader = new DataStreamReader(data); - q.PushReader(reader); - - var message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - reader = new DataStreamReader(data); - q.PushReader(reader); - - message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedReceiveQueue_PushReader_ToEmptyQueue() - { - var dataLength = sizeof(int) + 1; - - var data = new NativeArray(dataLength, Allocator.Temp); - - var writer = new DataStreamWriter(data); - writer.WriteInt(1); - writer.WriteByte(42); - - var reader = new DataStreamReader(data); - var q = new BatchedReceiveQueue(reader); - - Assert.False(q.IsEmpty); - - q.PopMessage(); - - Assert.True(q.IsEmpty); - - reader = new DataStreamReader(data); - q.PushReader(reader); - - var message = q.PopMessage(); - Assert.AreEqual(1, message.Count); - Assert.AreEqual((byte)42, message.Array[message.Offset]); - - Assert.AreEqual(default(ArraySegment), q.PopMessage()); - Assert.True(q.IsEmpty); - } - } -} diff --git a/Tests/Editor/Transports/BatchedReceiveQueueTests.cs.meta b/Tests/Editor/Transports/BatchedReceiveQueueTests.cs.meta deleted file mode 100644 index 7d0297b..0000000 --- a/Tests/Editor/Transports/BatchedReceiveQueueTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aabb21b30a80142ea86e59d1b4d5c587 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Transports/BatchedSendQueueTests.cs b/Tests/Editor/Transports/BatchedSendQueueTests.cs deleted file mode 100644 index 3ad4de1..0000000 --- a/Tests/Editor/Transports/BatchedSendQueueTests.cs +++ /dev/null @@ -1,396 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.Transports.UTP; -#if !UTP_TRANSPORT_2_0_ABOVE -using Unity.Networking.Transport; -#endif - -namespace Unity.Netcode.EditorTests -{ - internal class BatchedSendQueueTests - { - private const int k_TestQueueCapacity = 16 * 1024; - private const int k_TestMessageSize = 1020; - private const int k_NumMessagesToFillQueue = k_TestQueueCapacity / (k_TestMessageSize + BatchedSendQueue.PerMessageOverhead); - - private ArraySegment m_TestMessage; - - private void AssertIsTestMessage(NativeArray data) - { - var reader = new DataStreamReader(data); - Assert.AreEqual(k_TestMessageSize, reader.ReadInt()); - for (int i = 0; i < k_TestMessageSize; i++) - { - Assert.AreEqual(m_TestMessage.Array[i], reader.ReadByte()); - } - } - - [OneTimeSetUp] - public void InitializeTestMessage() - { - var data = new byte[k_TestMessageSize]; - for (int i = 0; i < k_TestMessageSize; i++) - { - data[i] = (byte)i; - } - m_TestMessage = new ArraySegment(data); - } - - [Test] - public void BatchedSendQueue_EmptyOnCreation() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - Assert.AreEqual(0, q.Length); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedSendQueue_NotCreatedAfterDispose() - { - var q = new BatchedSendQueue(k_TestQueueCapacity); - q.Dispose(); - Assert.False(q.IsCreated); - } - - [Test] - public void BatchedSendQueue_InitialCapacityLessThanMaximum() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity); - } - - [Test] - public void BatchedSendQueue_PushMessage_ReturnValue() - { - // Will fit a single test message, but not two (with overhead included). - var queueCapacity = (k_TestMessageSize * 2) + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(queueCapacity); - - Assert.True(q.PushMessage(m_TestMessage)); - Assert.False(q.PushMessage(m_TestMessage)); - } - - [Test] - public void BatchedSendQueue_PushMessage_IncreasesLength() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - q.PushMessage(m_TestMessage); - Assert.AreEqual(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead, q.Length); - } - - [Test] - public void BatchedSendQueue_PushMessage_SucceedsAfterConsume() - { - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - var queueCapacity = messageLength * 2; - - using var q = new BatchedSendQueue(queueCapacity); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - q.Consume(messageLength); - Assert.IsTrue(q.PushMessage(m_TestMessage)); - Assert.AreEqual(queueCapacity, q.Length); - } - - [Test] - public void BatchedSendQueue_PushMessage_GrowsDataIfNeeded() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity); - - var numMessagesToFillMinimum = BatchedSendQueue.MinimumMinimumCapacity / messageLength; - for (int i = 0; i < numMessagesToFillMinimum; i++) - { - q.PushMessage(m_TestMessage); - } - - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity); - - q.PushMessage(m_TestMessage); - - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity * 2); - } - - [Test] - public void BatchedSendQueue_PushMessage_DoesNotGrowDataPastMaximum() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - for (int i = 0; i < k_NumMessagesToFillQueue; i++) - { - Assert.IsTrue(q.PushMessage(m_TestMessage)); - } - - Assert.AreEqual(q.Capacity, k_TestQueueCapacity); - Assert.IsFalse(q.PushMessage(m_TestMessage)); - Assert.AreEqual(q.Capacity, k_TestQueueCapacity); - } - - [Test] - public void BatchedSendQueue_PushMessage_TrimsDataAfterGrowing() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - for (int i = 0; i < k_NumMessagesToFillQueue; i++) - { - Assert.IsTrue(q.PushMessage(m_TestMessage)); - } - - Assert.AreEqual(q.Capacity, k_TestQueueCapacity); - q.Consume(messageLength * (k_NumMessagesToFillQueue - 1)); - Assert.IsTrue(q.PushMessage(m_TestMessage)); - Assert.AreEqual(messageLength * 2, q.Length); - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity * 2); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_ReturnValue() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - var filled = q.FillWriterWithMessages(ref writer); - Assert.AreEqual(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead, filled); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_NoopIfNoPushedMessages() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(0, q.FillWriterWithMessages(ref writer)); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_NoopIfNotEnoughCapacity() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(2, Allocator.Temp); - - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(0, q.FillWriterWithMessages(ref writer)); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_SinglePushedMessage() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - q.FillWriterWithMessages(ref writer); - AssertIsTestMessage(data); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_MultiplePushedMessages() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - q.FillWriterWithMessages(ref writer); - - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - AssertIsTestMessage(data); - AssertIsTestMessage(data.GetSubArray(messageLength, messageLength)); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_PartialPushedMessages() - { - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(messageLength, Allocator.Temp); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(messageLength, q.FillWriterWithMessages(ref writer)); - AssertIsTestMessage(data); - - q.Consume(messageLength); - - writer = new DataStreamWriter(data); - Assert.AreEqual(messageLength, q.FillWriterWithMessages(ref writer)); - AssertIsTestMessage(data); - } - - [Test] - public void BatchedSendQueue_FillWriterWithMessages_StopOnSoftMaxBytes() - { - var smallMessage = new ArraySegment(new byte[10]); - var largeMessage = new ArraySegment(new byte[3000]); - - var smallMessageSize = smallMessage.Count + BatchedSendQueue.PerMessageOverhead; - var largeMessageSize = largeMessage.Count + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(largeMessageSize, Allocator.Temp); - - q.PushMessage(smallMessage); - q.PushMessage(largeMessage); - q.PushMessage(smallMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(smallMessageSize, q.FillWriterWithMessages(ref writer, 1000)); - q.Consume(smallMessageSize); - - writer = new DataStreamWriter(data); - Assert.AreEqual(largeMessageSize, q.FillWriterWithMessages(ref writer, 1000)); - q.Consume(largeMessageSize); - - writer = new DataStreamWriter(data); - Assert.AreEqual(smallMessageSize, q.FillWriterWithMessages(ref writer, 1000)); - q.Consume(smallMessageSize); - } - - [Test] - public void BatchedSendQueue_FillWriterWithBytes_NoopIfNoData() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(0, q.FillWriterWithBytes(ref writer)); - } - - [Test] - public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityMoreThanLength() - { - var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(k_TestQueueCapacity, Allocator.Temp); - - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer)); - AssertIsTestMessage(data); - } - - [Test] - public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityLessThanLength() - { - var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(dataLength, Allocator.Temp); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer)); - AssertIsTestMessage(data); - } - - [Test] - public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityEqualToLength() - { - var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(dataLength, Allocator.Temp); - - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer)); - AssertIsTestMessage(data); - } - - [Test] - public void BatchedSendQueue_FillWriterWithBytes_MaxBytesGreaterThanCapacity() - { - var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - - using var q = new BatchedSendQueue(k_TestQueueCapacity); - using var data = new NativeArray(dataLength, Allocator.Temp); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - var writer = new DataStreamWriter(data); - Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer, dataLength * 2)); - AssertIsTestMessage(data); - Assert.False(writer.HasFailedWrites); - } - - [Test] - public void BatchedSendQueue_Consume_LessThanLength() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - q.PushMessage(m_TestMessage); - q.PushMessage(m_TestMessage); - - var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead; - q.Consume(messageLength); - Assert.AreEqual(messageLength, q.Length); - } - - [Test] - public void BatchedSendQueue_Consume_ExactLength() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - q.PushMessage(m_TestMessage); - - q.Consume(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead); - Assert.AreEqual(0, q.Length); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedSendQueue_Consume_MoreThanLength() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - q.PushMessage(m_TestMessage); - - q.Consume(k_TestQueueCapacity); - Assert.AreEqual(0, q.Length); - Assert.True(q.IsEmpty); - } - - [Test] - public void BatchedSendQueue_Consume_TrimsDataOnEmpty() - { - using var q = new BatchedSendQueue(k_TestQueueCapacity); - - for (int i = 0; i < k_NumMessagesToFillQueue; i++) - { - q.PushMessage(m_TestMessage); - } - - Assert.AreEqual(q.Capacity, k_TestQueueCapacity); - q.Consume(k_TestQueueCapacity); - Assert.AreEqual(q.Capacity, BatchedSendQueue.MinimumMinimumCapacity); - } - } -} diff --git a/Tests/Editor/Transports/BatchedSendQueueTests.cs.meta b/Tests/Editor/Transports/BatchedSendQueueTests.cs.meta deleted file mode 100644 index 8107703..0000000 --- a/Tests/Editor/Transports/BatchedSendQueueTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 51a68dc80bf18443180f3600eb5890d7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Transports/UNetTransportTests.cs b/Tests/Editor/Transports/UNetTransportTests.cs deleted file mode 100644 index 9cb0bda..0000000 --- a/Tests/Editor/Transports/UNetTransportTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -#if UNITY_UNET_PRESENT -#pragma warning disable 618 // disable is obsolete -using NUnit.Framework; -using Unity.Netcode.Transports.UNET; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.EditorTests -{ - internal class UNetTransportTests - { - [Test] - public void StartServerReturnsFalseOnFailure() - { - UNetTransport unet1 = null; - UNetTransport unet2 = null; - - try - { - // Arrange - - // We're expecting an error from UNET, but don't care to validate the specific message - LogAssert.ignoreFailingMessages = true; - - var go = new GameObject(); - unet1 = go.AddComponent(); - unet1.ServerListenPort = 1; - unet1.Initialize(); - unet1.StartServer(); - unet2 = go.AddComponent(); - unet2.ServerListenPort = 1; - unet2.Initialize(); - - // Act - var result = unet2.StartServer(); - - // Assert - Assert.IsFalse(result, "UNET fails to initialize against port already in use"); - } - finally - { - unet1?.Shutdown(); - unet2?.Shutdown(); - } - } - } -} -#pragma warning restore 618 -#endif diff --git a/Tests/Editor/Transports/UNetTransportTests.cs.meta b/Tests/Editor/Transports/UNetTransportTests.cs.meta deleted file mode 100644 index 99744ac..0000000 --- a/Tests/Editor/Transports/UNetTransportTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6e328ef8f7c9b46538253a1b39dc8a97 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Transports/UnityTransportTests.cs b/Tests/Editor/Transports/UnityTransportTests.cs deleted file mode 100644 index 3bf49b6..0000000 --- a/Tests/Editor/Transports/UnityTransportTests.cs +++ /dev/null @@ -1,207 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.EditorTests -{ - internal class UnityTransportTests - { - [SetUp] - public void OnSetup() - { - ILPPMessageProvider.IntegrationTestNoMessages = true; - } - - [TearDown] - public void OnTearDown() - { - ILPPMessageProvider.IntegrationTestNoMessages = false; - } - - // Check that starting an IPv4 server succeeds. - [Test] - public void UnityTransport_BasicInitServer_IPv4() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - Assert.True(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that starting an IPv4 client succeeds. - [Test] - public void UnityTransport_BasicInitClient_IPv4() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - Assert.True(transport.StartClient()); - - transport.Shutdown(); - } - - // Check that starting an IPv6 server succeeds. - [Test] - public void UnityTransport_BasicInitServer_IPv6() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - transport.SetConnectionData("::1", 7777); - - Assert.True(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that starting an IPv6 client succeeds. - [Test] - public void UnityTransport_BasicInitClient_IPv6() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - transport.SetConnectionData("::1", 7777); - - Assert.True(transport.StartClient()); - - transport.Shutdown(); - } - - // Check that we can't restart a server. - [Test] - public void UnityTransport_NoRestartServer() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.StartServer(); - Assert.False(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that we can't restart a client. - [Test] - public void UnityTransport_NoRestartClient() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.StartClient(); - Assert.False(transport.StartClient()); - - transport.Shutdown(); - } - - // Check that we can't start both a server and client on the same transport. - [Test] - public void UnityTransport_NotBothServerAndClient() - { - UnityTransport transport; - - // Start server then client. - transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.StartServer(); - Assert.False(transport.StartClient()); - - transport.Shutdown(); - - // Start client then server. - transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.StartClient(); - Assert.False(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that restarting after failure succeeds. - [Test] - public void UnityTransport_RestartSucceedsAfterFailure() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.SetConnectionData("127.0.0.", 4242, "127.0.0."); - - Assert.False(transport.StartServer()); - - LogAssert.Expect(LogType.Error, "Invalid network endpoint: 127.0.0.:4242."); - LogAssert.Expect(LogType.Error, "Network listen address (127.0.0.) is Invalid!"); - - transport.SetConnectionData("127.0.0.1", 4242, "127.0.0.1"); - Assert.True(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that leaving all addresses empty is valid. - [Test] - public void UnityTransport_StartServerWithoutAddresses() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.SetConnectionData(string.Empty, 4242); - Assert.True(transport.StartServer()); - - transport.Shutdown(); - } - - // Check that StartClient returns false with bad connection data. - [Test] - public void UnityTransport_StartClientFailsWithBadAddress() - { - UnityTransport transport = new GameObject().AddComponent(); - transport.Initialize(); - - transport.SetConnectionData("foobar", 4242); - Assert.False(transport.StartClient()); - - LogAssert.Expect(LogType.Error, "Invalid network endpoint: foobar:4242."); - LogAssert.Expect(LogType.Error, "Target server network address (foobar) is Invalid!"); - - transport.Shutdown(); - } - -#if UTP_TRANSPORT_2_0_ABOVE - [Test] - public void UnityTransport_EmptySecurityStringsShouldThrow([Values("", null)] string cert, [Values("", null)] string secret) - { - var supportingGO = new GameObject(); - try - { - var networkManager = supportingGO.AddComponent(); // NM is required for UTP to work with certificates. - networkManager.NetworkConfig = new NetworkConfig(); - UnityTransport transport = supportingGO.AddComponent(); - networkManager.NetworkConfig.NetworkTransport = transport; - transport.Initialize(); - transport.SetServerSecrets(serverCertificate: cert, serverPrivateKey: secret); - - // Use encryption, but don't set certificate and check for exception - transport.UseEncryption = true; - Assert.Throws(() => - { - networkManager.StartServer(); - }); - // Make sure StartServer failed - Assert.False(transport.NetworkDriver.IsCreated); - Assert.False(networkManager.IsServer); - Assert.False(networkManager.IsListening); - } - finally - { - if (supportingGO != null) - { - Object.DestroyImmediate(supportingGO); - } - } - } -#endif - } -} diff --git a/Tests/Editor/Transports/UnityTransportTests.cs.meta b/Tests/Editor/Transports/UnityTransportTests.cs.meta deleted file mode 100644 index 8399287..0000000 --- a/Tests/Editor/Transports/UnityTransportTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1b0137a26ef0140f0bf5167c09eecb96 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/XXHashTests.cs b/Tests/Editor/XXHashTests.cs deleted file mode 100644 index 30fbb52..0000000 --- a/Tests/Editor/XXHashTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NUnit.Framework; - -namespace Unity.Netcode.EditorTests -{ - internal class XXHashTests - { - [Test] - public void TestXXHash32Short() - { - Assert.That("TestStuff".Hash32(), Is.EqualTo(0x64e10c4c)); - } - - [Test] - public void TestXXHash32Long() - { - Assert.That("TestingHashingWithLongStringValues".Hash32(), Is.EqualTo(0xba3d1783)); - } - - [Test] - public void TestXXHas64Short() - { - Assert.That("TestStuff".Hash64(), Is.EqualTo(0x4c3be8d82d14a5a9)); - } - - [Test] - public void TestXXHash64Long() - { - Assert.That("TestingHashingWithLongStringValues".Hash64(), Is.EqualTo(0x5b374f98b10bf246)); - } - } -} diff --git a/Tests/Editor/XXHashTests.cs.meta b/Tests/Editor/XXHashTests.cs.meta deleted file mode 100644 index a7886b3..0000000 --- a/Tests/Editor/XXHashTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ce9bdc7200b66410286810307554534b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/com.unity.netcode.editortests.asmdef b/Tests/Editor/com.unity.netcode.editortests.asmdef deleted file mode 100644 index 56d2377..0000000 --- a/Tests/Editor/com.unity.netcode.editortests.asmdef +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "Unity.Netcode.EditorTests", - "rootNamespace": "Unity.Netcode.EditorTests", - "references": [ - "Unity.Collections", - "Unity.Netcode.Runtime", - "Unity.Netcode.Editor", - "Unity.Netcode.Components", - "Unity.Multiplayer.MetricTypes", - "Unity.Multiplayer.NetStats", - "Unity.Multiplayer.Tools.MetricTypes", - "Unity.Multiplayer.Tools.NetStats", - "Unity.Networking.Transport", - "Unity.Mathematics" - ], - "optionalUnityReferences": [ - "TestAssemblies" - ], - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], - "includePlatforms": [ - "Editor" - ], - "allowUnsafeCode": true, - "versionDefines": [ - { - "name": "com.unity.multiplayer.tools", - "expression": "", - "define": "MULTIPLAYER_TOOLS" - }, - { - "name": "Unity", - "expression": "(0,2022.2.0a5)", - "define": "UNITY_UNET_PRESENT" - }, - { - "name": "com.unity.transport", - "expression": "2.0.0-exp", - "define": "UTP_TRANSPORT_2_0_ABOVE" - } - ] -} diff --git a/Tests/Editor/com.unity.netcode.editortests.asmdef.meta b/Tests/Editor/com.unity.netcode.editortests.asmdef.meta deleted file mode 100644 index ab7cbd5..0000000 --- a/Tests/Editor/com.unity.netcode.editortests.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 072b82e2b7c1dcf439827d3fbc4f52a1 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime.meta b/Tests/Runtime.meta deleted file mode 100644 index 112ba35..0000000 --- a/Tests/Runtime.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9d3a545f9ce7b074c95a3b1c3101dee9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/AddNetworkPrefabTests.cs b/Tests/Runtime/AddNetworkPrefabTests.cs deleted file mode 100644 index 4627143..0000000 --- a/Tests/Runtime/AddNetworkPrefabTests.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class AddNetworkPrefabTest : NetcodeIntegrationTest - { - internal class EmptyComponent : NetworkBehaviour - { - - } - protected override int NumberOfClients => 1; - - private GameObject m_Prefab; - - protected override IEnumerator OnSetup() - { - // Host is irrelevant, messages don't get sent to the host "client" - m_UseHost = false; - - yield return null; - } - - protected override void OnServerAndClientsCreated() - { - m_Prefab = new GameObject("Object"); - var networkObject = m_Prefab.AddComponent(); - m_Prefab.AddComponent(); - - // Make it a prefab - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject); - - m_ServerNetworkManager.NetworkConfig.SpawnTimeout = 0; - m_ServerNetworkManager.NetworkConfig.ForceSamePrefabs = false; - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = 0; - client.NetworkConfig.ForceSamePrefabs = false; - } - } - - private EmptyComponent GetObjectForClient(ulong clientId) - { -#if UNITY_2023_1_OR_NEWER - var emptyComponents = Object.FindObjectsByType(FindObjectsSortMode.InstanceID); -#else - var emptyComponents = Object.FindObjectsOfType(); -#endif - foreach (var component in emptyComponents) - { - if (component.IsSpawned && component.NetworkManager.LocalClientId == clientId) - { - return component; - } - } - return null; - } - - private void RegisterPrefab() - { - m_ServerNetworkManager.AddNetworkPrefab(m_Prefab); - foreach (var client in m_ClientNetworkManagers) - { - client.AddNetworkPrefab(m_Prefab); - } - } - - private void DeregisterPrefab() - { - m_ServerNetworkManager.RemoveNetworkPrefab(m_Prefab); - foreach (var client in m_ClientNetworkManagers) - { - client.RemoveNetworkPrefab(m_Prefab); - } - } - - private static CoroutineRunner s_CoroutineRunner; - - [UnityTest] - public IEnumerator WhenSpawningBeforeAddingPrefab_SpawnFails() - { - var serverObject = Object.Instantiate(m_Prefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - Assert.IsNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - } - - [UnityTest] - public IEnumerator WhenSpawningAfterAddingServerPrefabButBeforeAddingClientPrefab_SpawnFails() - { - m_ServerNetworkManager.AddNetworkPrefab(m_Prefab); - - var serverObject = Object.Instantiate(m_Prefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - Assert.IsNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - } - - [UnityTest] - public IEnumerator WhenSpawningAfterAddingPrefabOnServerAndClient_SpawnSucceeds() - { - RegisterPrefab(); - - var serverObject = Object.Instantiate(m_Prefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeHandled(m_ClientNetworkManagers[0]); - Assert.IsNotNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - } - - [UnityTest] - public IEnumerator WhenSpawningAfterRemovingPrefabOnClient_SpawnFails() - { - RegisterPrefab(); - - var serverObject = Object.Instantiate(m_Prefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - Assert.IsNotNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - - serverObject.GetComponent().Despawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - Assert.IsNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - - DeregisterPrefab(); - - serverObject = Object.Instantiate(m_Prefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - Assert.IsNull(GetObjectForClient(m_ClientNetworkManagers[0].LocalClientId)); - } - } -} diff --git a/Tests/Runtime/AddNetworkPrefabTests.cs.meta b/Tests/Runtime/AddNetworkPrefabTests.cs.meta deleted file mode 100644 index 4d1058a..0000000 --- a/Tests/Runtime/AddNetworkPrefabTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 67012fa25fe64aeda8fbf60340c1bc2f -timeCreated: 1652205947 \ No newline at end of file diff --git a/Tests/Runtime/AssemblyInfo.cs b/Tests/Runtime/AssemblyInfo.cs deleted file mode 100644 index fb444ea..0000000 --- a/Tests/Runtime/AssemblyInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Runtime.CompilerServices; - -#if UNITY_INCLUDE_TESTS -[assembly: InternalsVisibleTo("TestProject.RuntimeTests")] -#if UNITY_EDITOR -[assembly: InternalsVisibleTo("TestProject.EditorTests")] -#endif // UNITY_EDITOR -#if MULTIPLAYER_TOOLS -[assembly: InternalsVisibleTo("TestProject.ToolsIntegration.RuntimeTests")] -#endif // MULTIPLAYER_TOOLS -#endif // UNITY_INCLUDE_TESTS diff --git a/Tests/Runtime/AssemblyInfo.cs.meta b/Tests/Runtime/AssemblyInfo.cs.meta deleted file mode 100644 index e1f992f..0000000 --- a/Tests/Runtime/AssemblyInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5751b3c3bb5621e4686249b8083be068 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/ClientApprovalDenied.cs b/Tests/Runtime/ClientApprovalDenied.cs deleted file mode 100644 index fd0517d..0000000 --- a/Tests/Runtime/ClientApprovalDenied.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class ClientApprovalDenied : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - private bool m_ApproveConnection = true; - private ulong m_PendingClientId = 0; - private ulong m_DisconnectedClientId = 0; - - private List m_DisconnectedClientIdentifiers = new List(); - - private void ConnectionApproval(NetworkManager.ConnectionApprovalRequest connectionApprovalRequest, NetworkManager.ConnectionApprovalResponse connectionApprovalResponse) - { - connectionApprovalResponse.Approved = m_ApproveConnection; - connectionApprovalResponse.CreatePlayerObject = true; - // When denied, store the client identifier to use for validating the client disconnected notification identifier matches - if (!m_ApproveConnection) - { - m_PendingClientId = connectionApprovalRequest.ClientNetworkId; - } - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.ConnectionApproval = true; - base.OnNewClientCreated(networkManager); - } - - protected override bool ShouldWaitForNewClientToConnect(NetworkManager networkManager) - { - return false; - } - - /// - /// Validates that when a pending client is denied approval the server-host - /// OnClientDisconnected method will return the valid pending client identifier. - /// - [UnityTest] - public IEnumerator ClientDeniedAndDisconnectionNotificationTest() - { - m_ServerNetworkManager.NetworkConfig.ConnectionApproval = true; - m_ServerNetworkManager.ConnectionApprovalCallback = ConnectionApproval; - m_ApproveConnection = false; - m_ServerNetworkManager.OnClientDisconnectCallback += OnClientDisconnectCallback; - yield return CreateAndStartNewClient(); - yield return WaitForConditionOrTimeOut(() => m_PendingClientId == m_DisconnectedClientId); - AssertOnTimeout($"Timed out waiting for disconnect notification for pending Client-{m_PendingClientId}!"); - - // Validate that we don't get multiple disconnect notifications for clients being disconnected - // Have a client disconnect remotely - m_ClientNetworkManagers[0].Shutdown(); - - // Have the server disconnect a client - m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[1].LocalClientId); - m_ServerNetworkManager.OnClientDisconnectCallback -= OnClientDisconnectCallback; - } - - private void OnClientDisconnectCallback(ulong clientId) - { - Assert.False(m_DisconnectedClientIdentifiers.Contains(clientId), $"Received two disconnect notifications from Client-{clientId}!"); - m_DisconnectedClientIdentifiers.Add(clientId); - m_DisconnectedClientId = clientId; - } - } -} diff --git a/Tests/Runtime/ClientApprovalDenied.cs.meta b/Tests/Runtime/ClientApprovalDenied.cs.meta deleted file mode 100644 index 8d904aa..0000000 --- a/Tests/Runtime/ClientApprovalDenied.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e46e2cb14a6d49c48bc8c33094467961 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/ClientOnlyConnectionTests.cs b/Tests/Runtime/ClientOnlyConnectionTests.cs deleted file mode 100644 index dbd97fa..0000000 --- a/Tests/Runtime/ClientOnlyConnectionTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.Transports.UTP; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class ClientOnlyConnectionTests - { - private NetworkManager m_ClientNetworkManager; - private GameObject m_NetworkManagerGameObject; - private WaitForSeconds m_DefaultWaitForTick = new WaitForSeconds(1.0f / 30); - private bool m_WasDisconnected; - private TimeoutHelper m_TimeoutHelper; - - [SetUp] - public void Setup() - { - m_WasDisconnected = false; - m_NetworkManagerGameObject = new GameObject(); - m_ClientNetworkManager = m_NetworkManagerGameObject.AddComponent(); - m_ClientNetworkManager.NetworkConfig = new NetworkConfig(); - // Default is 1000ms per connection attempt and 60 connection attempts (60s) - // Currently there is no easy way to set these values other than in-editor - var unityTransport = m_NetworkManagerGameObject.AddComponent(); - unityTransport.ConnectTimeoutMS = 1000; - unityTransport.MaxConnectAttempts = 1; - m_TimeoutHelper = new TimeoutHelper(2); - m_ClientNetworkManager.NetworkConfig.NetworkTransport = unityTransport; - } - - [UnityTest] - public IEnumerator ClientFailsToConnect() - { - // Wait for the disconnected event - m_ClientNetworkManager.OnClientDisconnectCallback += ClientNetworkManager_OnClientDisconnectCallback; - - // Only start the client (so it will timeout) - m_ClientNetworkManager.StartClient(); - - // Unity Transport throws an error when it times out - LogAssert.Expect(LogType.Error, "Failed to connect to server."); - - yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_WasDisconnected, m_TimeoutHelper); - Assert.False(m_TimeoutHelper.TimedOut, "Timed out waiting for client to timeout waiting to connect!"); - - // Shutdown the client - m_ClientNetworkManager.Shutdown(); - - // Wait for a tick - yield return m_DefaultWaitForTick; - } - - private void ClientNetworkManager_OnClientDisconnectCallback(ulong clientId) - { - m_WasDisconnected = true; - } - - [TearDown] - public void TearDown() - { - if (m_NetworkManagerGameObject != null) - { - Object.DestroyImmediate(m_NetworkManagerGameObject); - } - } - } -} - diff --git a/Tests/Runtime/ClientOnlyConnectionTests.cs.meta b/Tests/Runtime/ClientOnlyConnectionTests.cs.meta deleted file mode 100644 index f6aaab9..0000000 --- a/Tests/Runtime/ClientOnlyConnectionTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 639fe2161ab25c54f94ce6eb991e668a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Components.meta b/Tests/Runtime/Components.meta deleted file mode 100644 index 9b77361..0000000 --- a/Tests/Runtime/Components.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 09f6601e441556642ab8217941b24e5c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Components/BufferDataValidationComponent.cs b/Tests/Runtime/Components/BufferDataValidationComponent.cs deleted file mode 100644 index 3e46ec4..0000000 --- a/Tests/Runtime/Components/BufferDataValidationComponent.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Collections.Generic; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Used in conjunction with the RpcQueueTest to validate from 1 byte to (n) MaximumBufferSize - /// - Sending and Receiving a continually growing buffer up to (MaximumBufferSize) - /// - Default maximum buffer size is 1MB - /// - internal class BufferDataValidationComponent : NetworkBehaviour - { - /// - /// Allows the external RPCQueueTest to begin testing or stop it - /// - public bool EnableTesting; - - /// - /// The maximum size of the buffer to send - /// - public int MaximumBufferSize = 1 << 15; - - /// - /// The rate at which the buffer size increases until it reaches MaximumBufferSize - /// (the default starting buffer size is 1 bytes) - /// - public int BufferSizeStart = 1; - - /// - /// Is checked to determine if the test exited because it failed - /// - public bool TestFailed { get; internal set; } - - private bool m_WaitForValidation; - private int m_CurrentBufferSize; - - private List m_SendBuffer; - private List m_PreCalculatedBufferValues; - - // Start is called before the first frame update - private void Start() - { - m_WaitForValidation = false; - m_CurrentBufferSize = BufferSizeStart; - m_SendBuffer = new List(MaximumBufferSize + 1); - m_PreCalculatedBufferValues = new List(MaximumBufferSize + 1); - while (m_PreCalculatedBufferValues.Count <= MaximumBufferSize) - { - m_PreCalculatedBufferValues.Add((byte)Random.Range(0, 255)); - } - } - - /// - /// Returns back whether the test has completed the total number of iterations - /// - /// - public bool IsTestComplete() - { - if (m_CurrentBufferSize > MaximumBufferSize || TestFailed) - { - return true; - } - return false; - } - - // Update is called once per frame - private void Update() - { - if (NetworkManager.Singleton.IsListening && EnableTesting && !IsTestComplete() && !m_WaitForValidation) - { - m_SendBuffer.Clear(); - //Keep the current contents of the bufffer and fill the buffer with the delta difference of the buffer's current size and new size from the m_PreCalculatedBufferValues - m_SendBuffer.AddRange(m_PreCalculatedBufferValues.GetRange(0, m_CurrentBufferSize)); - - //Make sure we don't do anything until we finish validating buffer - m_WaitForValidation = true; - - //Send the buffer - SendBufferServerRpc(m_SendBuffer.ToArray()); - } - } - - /// - /// Server side RPC for testing - /// - /// server rpc parameters - [ServerRpc] - private void SendBufferServerRpc(byte[] buffer) - { - TestFailed = !NetworkManagerHelper.BuffersMatch(0, buffer.Length, buffer, m_SendBuffer.ToArray()); - if (!TestFailed) - { - Debug.Log($"Tested buffer size of {m_SendBuffer.Count} -- OK"); - } - - if (m_CurrentBufferSize == MaximumBufferSize) - { - m_CurrentBufferSize++; - } - else - { - //Increasse buffer size - m_CurrentBufferSize = m_CurrentBufferSize << 1; - } - - m_WaitForValidation = false; - } - } -} diff --git a/Tests/Runtime/Components/BufferDataValidationComponent.cs.meta b/Tests/Runtime/Components/BufferDataValidationComponent.cs.meta deleted file mode 100644 index e1b3497..0000000 --- a/Tests/Runtime/Components/BufferDataValidationComponent.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1bb4bf89a220a8b409a4afb1f0f4eced -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Components/NetworkVariableTestComponent.cs b/Tests/Runtime/Components/NetworkVariableTestComponent.cs deleted file mode 100644 index 346b908..0000000 --- a/Tests/Runtime/Components/NetworkVariableTestComponent.cs +++ /dev/null @@ -1,466 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class EmbeddedManagedNetworkSerializableType : INetworkSerializable - { - public int Int; - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Int); - } - } - internal class ManagedNetworkSerializableType : INetworkSerializable, IEquatable - { - public string Str = ""; - public int[] Ints = Array.Empty(); - public EmbeddedManagedNetworkSerializableType Embedded = new EmbeddedManagedNetworkSerializableType(); - public int InMemoryValue; - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Str, true); - var length = Ints.Length; - serializer.SerializeValue(ref length); - if (serializer.IsReader) - { - Ints = new int[length]; - } - - for (var i = 0; i < length; ++i) - { - var val = Ints[i]; - serializer.SerializeValue(ref val); - Ints[i] = val; - } - - serializer.SerializeValue(ref Embedded); - } - - public bool Equals(ManagedNetworkSerializableType other) - { - if (ReferenceEquals(null, other)) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - if (Str != other.Str) - { - return false; - } - - if (Ints.Length != other.Ints.Length) - { - return false; - } - - for (var i = 0; i < Ints.Length; ++i) - { - if (Ints[i] != other.Ints[i]) - { - return false; - } - } - - if (Embedded.Int != other.Embedded.Int) - { - return false; - } - - return true; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj.GetType() != GetType()) - { - return false; - } - - return Equals((ManagedNetworkSerializableType)obj); - } - - public override int GetHashCode() - { - return 0; - } - } - internal struct UnmanagedNetworkSerializableType : INetworkSerializable, IEquatable - { - public FixedString32Bytes Str; - public int Int; - public int InMemoryValue; - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Str); - serializer.SerializeValue(ref Int); - } - - public bool Equals(UnmanagedNetworkSerializableType other) - { - return Str.Equals(other.Str) && Int == other.Int; - } - - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - - if (obj.GetType() != GetType()) - { - return false; - } - - return Equals((ManagedNetworkSerializableType)obj); - } - - public override int GetHashCode() - { - return Str.GetHashCode() ^ Int.GetHashCode() ^ InMemoryValue.GetHashCode(); - } - } - - - internal struct UnmanagedTemplateNetworkSerializableType : INetworkSerializable where T : unmanaged, INetworkSerializable - { - public T Value; - - public void NetworkSerialize(BufferSerializer serializer) where TReaderWriterType : IReaderWriter - { - serializer.SerializeValue(ref Value); - } - } - - internal struct ManagedTemplateNetworkSerializableType : INetworkSerializable where T : class, INetworkSerializable, new() - { - public T Value; - - public void NetworkSerialize(BufferSerializer serializer) where TReaderWriterType : IReaderWriter - { - bool isNull = Value == null; - serializer.SerializeValue(ref isNull); - if (!isNull) - { - if (Value == null) - { - Value = new T(); - } - serializer.SerializeValue(ref Value); - } - } - } - - /// - /// This provides coverage for all of the predefined NetworkVariable types - /// The initial goal is for generalized full coverage of NetworkVariables: - /// Covers all of the various constructor calls (i.e. various parameters or no parameters) - /// Covers the local NetworkVariable's OnValueChanged functionality (i.e. when a specific type changes do we get a notification?) - /// This was built as a NetworkBehaviour for further client-server unit testing patterns when this capability is available. - /// - internal class NetworkVariableTestComponent : NetworkBehaviour - { - private NetworkVariable m_NetworkVariableBool = new NetworkVariable(); - private NetworkVariable m_NetworkVariableByte = new NetworkVariable(); - private NetworkVariable m_NetworkVariableColor = new NetworkVariable(); - private NetworkVariable m_NetworkVariableColor32 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableDouble = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFloat = new NetworkVariable(); - private NetworkVariable m_NetworkVariableInt = new NetworkVariable(); - private NetworkVariable m_NetworkVariableLong = new NetworkVariable(); - private NetworkVariable m_NetworkVariableSByte = new NetworkVariable(); - private NetworkVariable m_NetworkVariableQuaternion = new NetworkVariable(); - private NetworkVariable m_NetworkVariableShort = new NetworkVariable(); - private NetworkVariable m_NetworkVariableVector4 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableVector3 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableVector2 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableRay = new NetworkVariable(); - private NetworkVariable m_NetworkVariableULong = new NetworkVariable(); - private NetworkVariable m_NetworkVariableUInt = new NetworkVariable(); - private NetworkVariable m_NetworkVariableUShort = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFixedString32 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFixedString64 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFixedString128 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFixedString512 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableFixedString4096 = new NetworkVariable(); - private NetworkVariable m_NetworkVariableManaged = new NetworkVariable(); - - - public NetworkVariableHelper Bool_Var; - public NetworkVariableHelper Byte_Var; - public NetworkVariableHelper Color_Var; - public NetworkVariableHelper Color32_Var; - public NetworkVariableHelper Double_Var; - public NetworkVariableHelper Float_Var; - public NetworkVariableHelper Int_Var; - public NetworkVariableHelper Long_Var; - public NetworkVariableHelper Sbyte_Var; - public NetworkVariableHelper Quaternion_Var; - public NetworkVariableHelper Short_Var; - public NetworkVariableHelper Vector4_Var; - public NetworkVariableHelper Vector3_Var; - public NetworkVariableHelper Vector2_Var; - public NetworkVariableHelper Ray_Var; - public NetworkVariableHelper Ulong_Var; - public NetworkVariableHelper Uint_Var; - public NetworkVariableHelper Ushort_Var; - public NetworkVariableHelper FixedString32_Var; - public NetworkVariableHelper FixedString64_Var; - public NetworkVariableHelper FixedString128_Var; - public NetworkVariableHelper FixedString512_Var; - public NetworkVariableHelper FixedString4096_Var; - public NetworkVariableHelper Managed_Var; - - - public bool EnableTesting; - private bool m_FinishedTests; - private bool m_ChangesAppliedToNetworkVariables; - - private float m_WaitForChangesTimeout; - - // Start is called before the first frame update - private void InitializeTest() - { - // Generic Constructor Test Coverage - m_NetworkVariableBool = new NetworkVariable(); - m_NetworkVariableByte = new NetworkVariable(); - m_NetworkVariableColor = new NetworkVariable(); - m_NetworkVariableColor32 = new NetworkVariable(); - m_NetworkVariableDouble = new NetworkVariable(); - m_NetworkVariableFloat = new NetworkVariable(); - m_NetworkVariableInt = new NetworkVariable(); - m_NetworkVariableLong = new NetworkVariable(); - m_NetworkVariableSByte = new NetworkVariable(); - m_NetworkVariableQuaternion = new NetworkVariable(); - m_NetworkVariableShort = new NetworkVariable(); - m_NetworkVariableVector4 = new NetworkVariable(); - m_NetworkVariableVector3 = new NetworkVariable(); - m_NetworkVariableVector2 = new NetworkVariable(); - m_NetworkVariableRay = new NetworkVariable(); - m_NetworkVariableULong = new NetworkVariable(); - m_NetworkVariableUInt = new NetworkVariable(); - m_NetworkVariableUShort = new NetworkVariable(); - m_NetworkVariableFixedString32 = new NetworkVariable(); - m_NetworkVariableFixedString64 = new NetworkVariable(); - m_NetworkVariableFixedString128 = new NetworkVariable(); - m_NetworkVariableFixedString512 = new NetworkVariable(); - m_NetworkVariableFixedString4096 = new NetworkVariable(); - m_NetworkVariableManaged = new NetworkVariable(); - - - // NetworkVariable Value Type Constructor Test Coverage - m_NetworkVariableBool = new NetworkVariable(true); - m_NetworkVariableByte = new NetworkVariable(0); - m_NetworkVariableColor = new NetworkVariable(new Color(1, 1, 1, 1)); - m_NetworkVariableColor32 = new NetworkVariable(new Color32(1, 1, 1, 1)); - m_NetworkVariableDouble = new NetworkVariable(1.0); - m_NetworkVariableFloat = new NetworkVariable(1.0f); - m_NetworkVariableInt = new NetworkVariable(1); - m_NetworkVariableLong = new NetworkVariable(1); - m_NetworkVariableSByte = new NetworkVariable(0); - m_NetworkVariableQuaternion = new NetworkVariable(Quaternion.identity); - m_NetworkVariableShort = new NetworkVariable(256); - m_NetworkVariableVector4 = new NetworkVariable(new Vector4(1, 1, 1, 1)); - m_NetworkVariableVector3 = new NetworkVariable(new Vector3(1, 1, 1)); - m_NetworkVariableVector2 = new NetworkVariable(new Vector2(1, 1)); - m_NetworkVariableRay = new NetworkVariable(new Ray()); - m_NetworkVariableULong = new NetworkVariable(1); - m_NetworkVariableUInt = new NetworkVariable(1); - m_NetworkVariableUShort = new NetworkVariable(1); - m_NetworkVariableFixedString32 = new NetworkVariable("1234567890"); - m_NetworkVariableFixedString64 = new NetworkVariable("1234567890"); - m_NetworkVariableFixedString128 = new NetworkVariable("1234567890"); - m_NetworkVariableFixedString512 = new NetworkVariable("1234567890"); - m_NetworkVariableFixedString4096 = new NetworkVariable("1234567890"); - m_NetworkVariableManaged = new NetworkVariable(new ManagedNetworkSerializableType - { - Str = "1234567890", - Ints = new[] { 1, 2, 3, 4, 5 }, - Embedded = new EmbeddedManagedNetworkSerializableType { Int = 6 } - }); - - // Use this nifty class: NetworkVariableHelper - // Tracks if NetworkVariable changed invokes the OnValueChanged callback for the given instance type - Bool_Var = new NetworkVariableHelper(m_NetworkVariableBool); - Byte_Var = new NetworkVariableHelper(m_NetworkVariableByte); - Color_Var = new NetworkVariableHelper(m_NetworkVariableColor); - Color32_Var = new NetworkVariableHelper(m_NetworkVariableColor32); - Double_Var = new NetworkVariableHelper(m_NetworkVariableDouble); - Float_Var = new NetworkVariableHelper(m_NetworkVariableFloat); - Int_Var = new NetworkVariableHelper(m_NetworkVariableInt); - Long_Var = new NetworkVariableHelper(m_NetworkVariableLong); - Sbyte_Var = new NetworkVariableHelper(m_NetworkVariableSByte); - Quaternion_Var = new NetworkVariableHelper(m_NetworkVariableQuaternion); - Short_Var = new NetworkVariableHelper(m_NetworkVariableShort); - Vector4_Var = new NetworkVariableHelper(m_NetworkVariableVector4); - Vector3_Var = new NetworkVariableHelper(m_NetworkVariableVector3); - Vector2_Var = new NetworkVariableHelper(m_NetworkVariableVector2); - Ray_Var = new NetworkVariableHelper(m_NetworkVariableRay); - Ulong_Var = new NetworkVariableHelper(m_NetworkVariableULong); - Uint_Var = new NetworkVariableHelper(m_NetworkVariableUInt); - Ushort_Var = new NetworkVariableHelper(m_NetworkVariableUShort); - FixedString32_Var = new NetworkVariableHelper(m_NetworkVariableFixedString32); - FixedString64_Var = new NetworkVariableHelper(m_NetworkVariableFixedString64); - FixedString128_Var = new NetworkVariableHelper(m_NetworkVariableFixedString128); - FixedString512_Var = new NetworkVariableHelper(m_NetworkVariableFixedString512); - FixedString4096_Var = new NetworkVariableHelper(m_NetworkVariableFixedString4096); - Managed_Var = new NetworkVariableHelper(m_NetworkVariableManaged); - } - - /// - /// Test result for all values changed the expected number of times (once per unique NetworkVariable type) - /// - public bool DidAllValuesChange() - { - if (NetworkVariableBaseHelper.VarChangedCount == NetworkVariableBaseHelper.InstanceCount) - { - return true; - } - else - { - return false; - } - } - - /// - /// Returns back whether the test has completed the total number of iterations - /// - public bool IsTestComplete() - { - return m_FinishedTests; - } - - public void Awake() - { - InitializeTest(); - } - - public void AssertAllValuesAreCorrect() - { - Assert.AreEqual(false, m_NetworkVariableBool.Value); - Assert.AreEqual(255, m_NetworkVariableByte.Value); - Assert.AreEqual(100, m_NetworkVariableColor.Value.r); - Assert.AreEqual(100, m_NetworkVariableColor.Value.g); - Assert.AreEqual(100, m_NetworkVariableColor.Value.b); - Assert.AreEqual(100, m_NetworkVariableColor32.Value.r); - Assert.AreEqual(100, m_NetworkVariableColor32.Value.g); - Assert.AreEqual(100, m_NetworkVariableColor32.Value.b); - Assert.AreEqual(100, m_NetworkVariableColor32.Value.a); - Assert.AreEqual(1000, m_NetworkVariableDouble.Value); - Assert.AreEqual(1000.0f, m_NetworkVariableFloat.Value); - Assert.AreEqual(1000, m_NetworkVariableInt.Value); - Assert.AreEqual(100000, m_NetworkVariableLong.Value); - Assert.AreEqual(-127, m_NetworkVariableSByte.Value); - Assert.AreEqual(100, m_NetworkVariableQuaternion.Value.w); - Assert.AreEqual(100, m_NetworkVariableQuaternion.Value.x); - Assert.AreEqual(100, m_NetworkVariableQuaternion.Value.y); - Assert.AreEqual(100, m_NetworkVariableQuaternion.Value.z); - Assert.AreEqual(short.MaxValue, m_NetworkVariableShort.Value); - Assert.AreEqual(1000, m_NetworkVariableVector4.Value.w); - Assert.AreEqual(1000, m_NetworkVariableVector4.Value.x); - Assert.AreEqual(1000, m_NetworkVariableVector4.Value.y); - Assert.AreEqual(1000, m_NetworkVariableVector4.Value.z); - Assert.AreEqual(1000, m_NetworkVariableVector3.Value.x); - Assert.AreEqual(1000, m_NetworkVariableVector3.Value.y); - Assert.AreEqual(1000, m_NetworkVariableVector3.Value.z); - Assert.AreEqual(1000, m_NetworkVariableVector2.Value.x); - Assert.AreEqual(1000, m_NetworkVariableVector2.Value.y); - Assert.AreEqual(Vector3.one.x, m_NetworkVariableRay.Value.origin.x); - Assert.AreEqual(Vector3.one.y, m_NetworkVariableRay.Value.origin.y); - Assert.AreEqual(Vector3.one.z, m_NetworkVariableRay.Value.origin.z); - Assert.AreEqual(Vector3.right.x, m_NetworkVariableRay.Value.direction.x); - Assert.AreEqual(Vector3.right.y, m_NetworkVariableRay.Value.direction.y); - Assert.AreEqual(Vector3.right.z, m_NetworkVariableRay.Value.direction.z); - Assert.AreEqual(ulong.MaxValue, m_NetworkVariableULong.Value); - Assert.AreEqual(uint.MaxValue, m_NetworkVariableUInt.Value); - Assert.AreEqual(ushort.MaxValue, m_NetworkVariableUShort.Value); - Assert.IsTrue(m_NetworkVariableFixedString32.Value.Equals("FixedString32Bytes")); - Assert.IsTrue(m_NetworkVariableFixedString64.Value.Equals("FixedString64Bytes")); - Assert.IsTrue(m_NetworkVariableFixedString128.Value.Equals("FixedString128Bytes")); - Assert.IsTrue(m_NetworkVariableFixedString512.Value.Equals("FixedString512Bytes")); - Assert.IsTrue(m_NetworkVariableFixedString4096.Value.Equals("FixedString4096Bytes")); - Assert.IsTrue(m_NetworkVariableManaged.Value.Equals(new ManagedNetworkSerializableType - { - Str = "ManagedNetworkSerializableType", - Ints = new[] { 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 }, - Embedded = new EmbeddedManagedNetworkSerializableType { Int = 20000 } - })); - } - - // Update is called once per frame - private void Update() - { - if (EnableTesting) - { - //Added timeout functionality for near future changes to NetworkVariables - if (!m_FinishedTests && m_ChangesAppliedToNetworkVariables) - { - //We finish testing if all NetworkVariables changed their value or we timed out waiting for - //all NetworkVariables to change their value - m_FinishedTests = DidAllValuesChange() || (m_WaitForChangesTimeout < Time.realtimeSinceStartup); - } - else - { - if (NetworkManager != null && NetworkManager.IsListening) - { - //Now change all of the values to make sure we are at least testing the local callback - m_NetworkVariableBool.Value = false; - m_NetworkVariableByte.Value = 255; - m_NetworkVariableColor.Value = new Color(100, 100, 100); - m_NetworkVariableColor32.Value = new Color32(100, 100, 100, 100); - m_NetworkVariableDouble.Value = 1000; - m_NetworkVariableFloat.Value = 1000.0f; - m_NetworkVariableInt.Value = 1000; - m_NetworkVariableLong.Value = 100000; - m_NetworkVariableSByte.Value = -127; - m_NetworkVariableQuaternion.Value = new Quaternion(100, 100, 100, 100); - m_NetworkVariableShort.Value = short.MaxValue; - m_NetworkVariableVector4.Value = new Vector4(1000, 1000, 1000, 1000); - m_NetworkVariableVector3.Value = new Vector3(1000, 1000, 1000); - m_NetworkVariableVector2.Value = new Vector2(1000, 1000); - m_NetworkVariableRay.Value = new Ray(Vector3.one, Vector3.right); - m_NetworkVariableULong.Value = ulong.MaxValue; - m_NetworkVariableUInt.Value = uint.MaxValue; - m_NetworkVariableUShort.Value = ushort.MaxValue; - m_NetworkVariableFixedString32.Value = new FixedString32Bytes("FixedString32Bytes"); - m_NetworkVariableFixedString64.Value = new FixedString64Bytes("FixedString64Bytes"); - m_NetworkVariableFixedString128.Value = new FixedString128Bytes("FixedString128Bytes"); - m_NetworkVariableFixedString512.Value = new FixedString512Bytes("FixedString512Bytes"); - m_NetworkVariableFixedString4096.Value = new FixedString4096Bytes("FixedString4096Bytes"); - m_NetworkVariableManaged.Value = new ManagedNetworkSerializableType - { - Str = "ManagedNetworkSerializableType", - Ints = new[] { 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 }, - Embedded = new EmbeddedManagedNetworkSerializableType { Int = 20000 } - }; - - //Set the timeout (i.e. how long we will wait for all NetworkVariables to have registered their changes) - m_WaitForChangesTimeout = Time.realtimeSinceStartup + 0.50f; - m_ChangesAppliedToNetworkVariables = true; - } - } - } - } - } -} diff --git a/Tests/Runtime/Components/NetworkVariableTestComponent.cs.meta b/Tests/Runtime/Components/NetworkVariableTestComponent.cs.meta deleted file mode 100644 index d6f1e19..0000000 --- a/Tests/Runtime/Components/NetworkVariableTestComponent.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ef882d7ba8231eb45839424f54a12486 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Components/NetworkVisibilityComponent.cs b/Tests/Runtime/Components/NetworkVisibilityComponent.cs deleted file mode 100644 index 856e77a..0000000 --- a/Tests/Runtime/Components/NetworkVisibilityComponent.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkVisibilityComponent : NetworkBehaviour - { - public void Hide() - { - GetComponent().CheckObjectVisibility += HandleCheckObjectVisibility; - } - - protected virtual bool HandleCheckObjectVisibility(ulong clientId) => false; - - } -} diff --git a/Tests/Runtime/Components/NetworkVisibilityComponent.cs.meta b/Tests/Runtime/Components/NetworkVisibilityComponent.cs.meta deleted file mode 100644 index b148896..0000000 --- a/Tests/Runtime/Components/NetworkVisibilityComponent.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7c8284d1c5a9f4c3783a16e314376ea3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/ConnectionApproval.cs b/Tests/Runtime/ConnectionApproval.cs deleted file mode 100644 index efa19cf..0000000 --- a/Tests/Runtime/ConnectionApproval.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(PlayerCreation.Prefab)] - [TestFixture(PlayerCreation.PrefabHash)] - [TestFixture(PlayerCreation.NoPlayer)] - [TestFixture(PlayerCreation.FailValidation)] - internal class ConnectionApprovalTests : IntegrationTestWithApproximation - { - private const string k_InvalidToken = "Invalid validation token!"; - - public enum PlayerCreation - { - Prefab, - PrefabHash, - NoPlayer, - FailValidation - } - private PlayerCreation m_PlayerCreation; - private bool m_ClientDisconnectReasonValidated; - private Vector3 m_ExpectedPosition; - private Quaternion m_ExpectedRotation; - - private Dictionary m_Validated = new Dictionary(); - - public ConnectionApprovalTests(PlayerCreation playerCreation) - { - m_PlayerCreation = playerCreation; - } - - protected override int NumberOfClients => 1; - - private Guid m_ValidationToken; - - protected override bool ShouldCheckForSpawnedPlayers() - { - return m_PlayerCreation != PlayerCreation.NoPlayer; - } - - protected override void OnServerAndClientsCreated() - { - if (m_PlayerCreation == PlayerCreation.Prefab || m_PlayerCreation == PlayerCreation.PrefabHash) - { - m_ExpectedPosition = GetRandomVector3(-10.0f, 10.0f); - m_ExpectedRotation = Quaternion.Euler(GetRandomVector3(-359.98f, 359.98f)); - } - - m_ClientDisconnectReasonValidated = false; - m_BypassConnectionTimeout = m_PlayerCreation == PlayerCreation.FailValidation; - m_Validated.Clear(); - m_ValidationToken = Guid.NewGuid(); - var validationToken = Encoding.UTF8.GetBytes(m_ValidationToken.ToString()); - m_ServerNetworkManager.ConnectionApprovalCallback = NetworkManagerObject_ConnectionApprovalCallback; - m_ServerNetworkManager.NetworkConfig.PlayerPrefab = m_PlayerCreation == PlayerCreation.Prefab ? m_PlayerPrefab : null; - if (m_PlayerCreation == PlayerCreation.PrefabHash) - { - m_ServerNetworkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Prefab = m_PlayerPrefab }); - } - m_ServerNetworkManager.NetworkConfig.ConnectionApproval = true; - m_ServerNetworkManager.NetworkConfig.ConnectionData = validationToken; - - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.PlayerPrefab = m_PlayerCreation == PlayerCreation.Prefab ? m_PlayerPrefab : null; - if (m_PlayerCreation == PlayerCreation.PrefabHash) - { - client.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Prefab = m_PlayerPrefab }); - } - client.NetworkConfig.ConnectionApproval = true; - client.NetworkConfig.ConnectionData = m_PlayerCreation == PlayerCreation.FailValidation ? Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()) : validationToken; - if (m_PlayerCreation == PlayerCreation.FailValidation) - { - client.OnClientDisconnectCallback += Client_OnClientDisconnectCallback; - } - } - - base.OnServerAndClientsCreated(); - } - - private void Client_OnClientDisconnectCallback(ulong clientId) - { - m_ClientNetworkManagers[0].OnClientDisconnectCallback -= Client_OnClientDisconnectCallback; - m_ClientDisconnectReasonValidated = m_ClientNetworkManagers[0].LocalClientId == clientId && m_ClientNetworkManagers[0].DisconnectReason == k_InvalidToken; - } - - private bool ClientAndHostValidated() - { - if (!m_Validated.ContainsKey(m_ServerNetworkManager.LocalClientId) || !m_Validated[m_ServerNetworkManager.LocalClientId]) - { - return false; - } - if (m_PlayerCreation == PlayerCreation.FailValidation) - { - return m_ClientDisconnectReasonValidated; - } - else - { - foreach (var client in m_ClientNetworkManagers) - { - if (!m_Validated.ContainsKey(client.LocalClientId) || !m_Validated[client.LocalClientId]) - { - return false; - } - } - } - return true; - } - - private bool ValidatePlayersPositionRotation() - { - foreach (var playerEntries in m_PlayerNetworkObjects) - { - foreach (var player in playerEntries.Value) - { - if (!Approximately(player.Value.transform.position, m_ExpectedPosition)) - { - return false; - } - if (!Approximately(player.Value.transform.rotation, m_ExpectedRotation)) - { - return false; - } - } - } - return true; - } - - [UnityTest] - public IEnumerator ConnectionApproval() - { - yield return WaitForConditionOrTimeOut(ClientAndHostValidated); - AssertOnTimeout("Timed out waiting for all clients to be approved!"); - - if (m_PlayerCreation == PlayerCreation.Prefab || m_PlayerCreation == PlayerCreation.PrefabHash) - { - yield return WaitForConditionOrTimeOut(ValidatePlayersPositionRotation); - AssertOnTimeout("Not all player prefabs spawned in the correct position and/or rotation!"); - } - } - - private void NetworkManagerObject_ConnectionApprovalCallback(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response) - { - var stringGuid = Encoding.UTF8.GetString(request.Payload); - - if (m_ValidationToken.ToString() == stringGuid) - { - m_Validated.Add(request.ClientNetworkId, true); - response.Approved = true; - } - else - { - response.Approved = false; - response.Reason = "Invalid validation token!"; - } - - response.CreatePlayerObject = ShouldCheckForSpawnedPlayers(); - response.Position = m_ExpectedPosition; - response.Rotation = m_ExpectedRotation; - response.PlayerPrefabHash = m_PlayerCreation == PlayerCreation.PrefabHash ? m_PlayerPrefab.GetComponent().GlobalObjectIdHash : null; - } - - - [Test] - public void VerifyUniqueNetworkConfigPerRequest() - { - var networkConfig = new NetworkConfig - { - EnableSceneManagement = true, - TickRate = 30 - }; - var currentHash = networkConfig.GetConfig(); - networkConfig.EnableSceneManagement = false; - networkConfig.TickRate = 60; - var newHash = networkConfig.GetConfig(false); - - Assert.True(currentHash != newHash, $"Hashed {nameof(NetworkConfig)} values {currentHash} and {newHash} should not be the same!"); - } - } -} - diff --git a/Tests/Runtime/ConnectionApproval.cs.meta b/Tests/Runtime/ConnectionApproval.cs.meta deleted file mode 100644 index 37a4ced..0000000 --- a/Tests/Runtime/ConnectionApproval.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 52ef2017d72b57f418907e98e1d8b90a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/ConnectionApprovalTimeoutTests.cs b/Tests/Runtime/ConnectionApprovalTimeoutTests.cs deleted file mode 100644 index db1210f..0000000 --- a/Tests/Runtime/ConnectionApprovalTimeoutTests.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Collections; -using System.Text.RegularExpressions; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(ApprovalTimedOutTypes.ServerDoesNotRespond)] - [TestFixture(ApprovalTimedOutTypes.ClientDoesNotRequest)] - internal class ConnectionApprovalTimeoutTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - public enum ApprovalTimedOutTypes - { - ClientDoesNotRequest, - ServerDoesNotRespond - } - - private ApprovalTimedOutTypes m_ApprovalFailureType; - - public ConnectionApprovalTimeoutTests(ApprovalTimedOutTypes approvalFailureType) - { - m_ApprovalFailureType = approvalFailureType; - } - - // Must be >= 5 since this is an int value and the test waits for timeout - 1 to try to verify it doesn't - // time out early - private const int k_TestTimeoutPeriod = 5; - - private Regex m_ExpectedLogMessage; - private LogType m_LogType; - - - protected override IEnumerator OnSetup() - { - m_BypassConnectionTimeout = true; - return base.OnSetup(); - } - - protected override IEnumerator OnTearDown() - { - m_BypassConnectionTimeout = false; - return base.OnTearDown(); - } - - protected override void OnServerAndClientsCreated() - { - m_ServerNetworkManager.NetworkConfig.ClientConnectionBufferTimeout = k_TestTimeoutPeriod; - m_ServerNetworkManager.LogLevel = LogLevel.Developer; - m_ClientNetworkManagers[0].NetworkConfig.ClientConnectionBufferTimeout = k_TestTimeoutPeriod; - m_ClientNetworkManagers[0].LogLevel = LogLevel.Developer; - base.OnServerAndClientsCreated(); - } - - protected override IEnumerator OnStartedServerAndClients() - { - if (m_ApprovalFailureType == ApprovalTimedOutTypes.ServerDoesNotRespond) - { - m_ServerNetworkManager.ConnectionManager.MockSkippingApproval = true; - // 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_ExpectedLogMessage = new Regex("Timed out waiting for the server to approve the connection request."); - m_LogType = LogType.Log; - } - else - { - // 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)); - - // 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."); - m_LogType = LogType.Warning; - } - yield return null; - } - - [UnityTest] - public IEnumerator ValidateApprovalTimeout() - { - // Just delay for a second - yield return new WaitForSeconds(k_TestTimeoutPeriod * 0.25f); - - // Verify we haven't received the time out message yet - NetcodeLogAssert.LogWasNotReceived(LogType.Log, m_ExpectedLogMessage); - - yield return new WaitForSeconds(k_TestTimeoutPeriod * 1.25f); - - // We should have the test relative log message by this time. - NetcodeLogAssert.LogWasReceived(m_LogType, m_ExpectedLogMessage); - - VerboseDebug("Checking connected client count"); - // It should only have the host client connected - Assert.AreEqual(1, m_ServerNetworkManager.ConnectedClients.Count, $"Expected only one client when there were {m_ServerNetworkManager.ConnectedClients.Count} clients connected!"); - - - 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!"); - } - } -} diff --git a/Tests/Runtime/ConnectionApprovalTimeoutTests.cs.meta b/Tests/Runtime/ConnectionApprovalTimeoutTests.cs.meta deleted file mode 100644 index 34b8e91..0000000 --- a/Tests/Runtime/ConnectionApprovalTimeoutTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b0c4159ea234415fa9497860e6ef4fc2 -timeCreated: 1661796642 \ No newline at end of file diff --git a/Tests/Runtime/DeferredMessagingTests.cs b/Tests/Runtime/DeferredMessagingTests.cs deleted file mode 100644 index bc97fd7..0000000 --- a/Tests/Runtime/DeferredMessagingTests.cs +++ /dev/null @@ -1,1340 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class TestDeferredMessageManager : DeferredMessageManager - { - public bool DeferMessageCalled; - public bool ProcessTriggersCalled; - - public delegate void BeforePurgeDelegate(TestDeferredMessageManager manager, ulong key); - public delegate void BeforeDeferDelegate(TestDeferredMessageManager manager, ulong key); - - public BeforePurgeDelegate OnBeforePurge; - public BeforeDeferDelegate OnBeforeDefer; - - // The way that OnBeforePurge gets used in these tests involves counting things that are still in the - // deferred message queue. This is something the base class doesn't support so the way it purges individual - // messages does not make it safe to access structures during purging. This set contains a list of - // keys that are unsafe to access because they've been purged/disposed, but not removed from the dictionary - // yet, so that we can avoid accessing those and record them instead as 0 (which is what they will be once - // the purge completes) - private HashSet m_PurgedKeys = new HashSet(); - - public TestDeferredMessageManager(NetworkManager networkManager) : - base(networkManager) - { - } - - public void ClearCallFlags() - { - DeferMessageCalled = false; - ProcessTriggersCalled = false; - } - - public int DeferredMessageCountTotal() - { - int ret = 0; - foreach (var kvp in m_Triggers) - { - ret += DeferredMessageCountForType(kvp.Key); - } - - return ret; - } - - public int DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType trigger) - { - var count = 0; - if (m_Triggers.TryGetValue(trigger, out var dict)) - { - foreach (var kvp in dict) - { - if (m_PurgedKeys.Contains(kvp.Key)) - { - continue; - } - count += kvp.Value.TriggerData.Length; - } - } - - return count; - } - - public int DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType trigger, ulong key) - { - if (m_PurgedKeys.Contains(key)) - { - return 0; - } - if (m_Triggers.TryGetValue(trigger, out var dict)) - { - if (dict.TryGetValue(key, out var subdict)) - { - return subdict.TriggerData.Length; - } - } - - return 0; - } - public override void DeferMessage(IDeferredNetworkMessageManager.TriggerType trigger, ulong key, FastBufferReader reader, ref NetworkContext context, string messageType) - { - OnBeforeDefer?.Invoke(this, key); - DeferMessageCalled = true; - base.DeferMessage(trigger, key, reader, ref context, messageType); - } - - public override void ProcessTriggers(IDeferredNetworkMessageManager.TriggerType trigger, ulong key) - { - if (trigger == IDeferredNetworkMessageManager.TriggerType.OnNextFrame) - { - return; - } - ProcessTriggersCalled = true; - base.ProcessTriggers(trigger, key); - } - - protected override void PurgeTrigger(IDeferredNetworkMessageManager.TriggerType triggerType, ulong key, TriggerInfo triggerInfo) - { - OnBeforePurge?.Invoke(this, key); - base.PurgeTrigger(triggerType, key, triggerInfo); - m_PurgedKeys.Add(key); - } - - public override void CleanupStaleTriggers() - { - base.CleanupStaleTriggers(); - m_PurgedKeys.Clear(); - } - } - - internal class DeferredMessageTestRpcComponent : NetworkBehaviour - { - public bool ClientRpcCalled; - - [ClientRpc] - public void SendTestClientRpc() - { - ClientRpcCalled = true; - } - - public static readonly List ClientInstances = new List(); - public override void OnNetworkSpawn() - { - if (!IsServer) - { - ClientInstances.Add(NetworkManager.LocalClientId); - } - base.OnNetworkSpawn(); - } - } - - internal class DeferredMessageTestNetworkVariableComponent : NetworkBehaviour - { - public static readonly List ClientInstances = new List(); - - public NetworkVariable TestNetworkVariable; - - public void Awake() - { - TestNetworkVariable = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - } - - public override void OnNetworkSpawn() - { - if (!IsServer) - { - ClientInstances.Add(NetworkManager.LocalClientId); - } - base.OnNetworkSpawn(); - } - } - - internal class DeferredMessageTestRpcAndNetworkVariableComponent : NetworkBehaviour - { - public static readonly List ClientInstances = new List(); - public bool ClientRpcCalled; - public NetworkVariable TestNetworkVariable; - - public void Awake() - { - TestNetworkVariable = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - } - - public override void OnNetworkSpawn() - { - if (!IsServer) - { - ClientInstances.Add(NetworkManager.LocalClientId); - } - base.OnNetworkSpawn(); - } - - [ClientRpc] - public void SendTestClientRpc() - { - ClientRpcCalled = true; - } - } - - internal class DeferredMessagingTest : NetcodeIntegrationTest - { - protected override int NumberOfClients => 0; - - private List> m_ClientSpawnCatchers = new List>(); - - private GameObject m_RpcPrefab; - private GameObject m_NetworkVariablePrefab; - private GameObject m_RpcAndNetworkVariablePrefab; - - private int m_NumberOfClientsToLateJoin = 2; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected override void OnInlineSetup() - { - // Revert back to standard deferred message format for tests (for now) - DeferredMessageManager.IncludeMessageType = false; - - DeferredMessageTestRpcAndNetworkVariableComponent.ClientInstances.Clear(); - DeferredMessageTestRpcComponent.ClientInstances.Clear(); - DeferredMessageTestNetworkVariableComponent.ClientInstances.Clear(); - m_SkipAddingPrefabsToClient = false; - // Host is irrelevant, messages don't get sent to the host "client" - m_UseHost = false; - - // Replace the IDeferredMessageManager component with our test one in the component factory - ComponentFactory.Register(networkManager => new TestDeferredMessageManager(networkManager)); - } - - protected override void OnInlineTearDown() - { - // Revert the IDeferredMessageManager component to its default (DeferredMessageManager) - ComponentFactory.Deregister(); - m_ClientSpawnCatchers.Clear(); - } - - protected override void OnServerAndClientsCreated() - { - // Note: This is where prefabs should be created - m_RpcPrefab = CreateNetworkObjectPrefab("Object With RPC"); - var networkObject = m_RpcPrefab.GetComponent(); - m_RpcPrefab.AddComponent(); - - m_NetworkVariablePrefab = CreateNetworkObjectPrefab("Object With NetworkVariable"); - networkObject = m_NetworkVariablePrefab.GetComponent(); - m_NetworkVariablePrefab.AddComponent(); - - m_RpcAndNetworkVariablePrefab = CreateNetworkObjectPrefab("Object With NetworkVariable And RPC"); - networkObject = m_RpcAndNetworkVariablePrefab.GetComponent(); - m_RpcAndNetworkVariablePrefab.AddComponent(); - - m_ServerNetworkManager.NetworkConfig.ForceSamePrefabs = false; - - } - - private bool m_SkipAddingPrefabsToClient = false; - - private void AddPrefabsToClient(NetworkManager networkManager) - { - networkManager.AddNetworkPrefab(m_RpcPrefab); - networkManager.AddNetworkPrefab(m_NetworkVariablePrefab); - networkManager.AddNetworkPrefab(m_RpcAndNetworkVariablePrefab); - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.ForceSamePrefabs = false; - if (!m_SkipAddingPrefabsToClient) - { - AddPrefabsToClient(networkManager); - } - - base.OnNewClientCreated(networkManager); - } - - private void SpawnClients(bool clearTestDeferredMessageManagerCallFlags = true) - { - for (int i = 0; i < m_NumberOfClientsToLateJoin; i++) - { - // Create and join client - CreateAndStartNewClientWithTimeTravel(); - } - - if (clearTestDeferredMessageManagerCallFlags) - { - ClearTestDeferredMessageManagerCallFlags(); - } - } - - private T GetComponentForClient(ulong clientId) where T : NetworkBehaviour - { -#if UNITY_2023_1_OR_NEWER - var componentsToFind = Object.FindObjectsByType(FindObjectsSortMode.InstanceID); -#else - var componentsToFind = Object.FindObjectsOfType(); -#endif - - foreach (var component in componentsToFind) - { - if (component.IsSpawned && component.NetworkManager.LocalClientId == clientId) - { - return component; - } - } - return null; - } - - private void CatchSpawns() - { - foreach (var client in m_ClientNetworkManagers) - { - var catcher = new MessageCatcher(client); - m_ClientSpawnCatchers.Add(catcher); - client.ConnectionManager.MessageManager.Hook(catcher); - } - } - - private void ReleaseSpawns() - { - for (var i = 0; i < m_ClientNetworkManagers.Length; ++i) - { - // Unhook first so the spawn catcher stops catching spawns - m_ClientNetworkManagers[i].ConnectionManager.MessageManager.Unhook(m_ClientSpawnCatchers[i]); - m_ClientSpawnCatchers[i].ReleaseMessages(); - } - m_ClientSpawnCatchers.Clear(); - } - - protected override void OnTimeTravelServerAndClientsConnected() - { - // Clear out these values from whatever might have set them during the initial startup. - ClearTestDeferredMessageManagerCallFlags(); - } - - private void WaitForClientsToCatchSpawns(int count = 1) - { - Assert.IsTrue(WaitForConditionOrTimeOutWithTimeTravel(() => - { - foreach (var catcher in m_ClientSpawnCatchers) - { - if (catcher.CaughtMessageCount != count) - { - return false; - } - } - - return true; - })); - } - - private void ClearTestDeferredMessageManagerCallFlags() - { - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.ClearCallFlags(); - } - } - - private void AssertSpawnTriggerCountForObject(TestDeferredMessageManager manager, GameObject serverObject, int expectedCount = 1) - { - Assert.AreEqual(expectedCount, manager.DeferredMessageCountTotal()); - Assert.AreEqual(expectedCount, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(expectedCount, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(0, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab)); - } - - private void WaitForAllClientsToReceive() where T : INetworkMessage - { - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList(), ReceiptType.Received); - } - - private void WaitForAllClientsToReceive() - where TFirstMessage : INetworkMessage - where TSecondMessage : INetworkMessage - { - WaitForMessagesReceivedWithTimeTravel(new List - { - typeof(TFirstMessage), - typeof(TSecondMessage) - }, m_ClientNetworkManagers.ToList(), ReceiptType.Received); - } - - private void WaitForAllClientsToReceive() - where TFirstMessage : INetworkMessage - where TSecondMessage : INetworkMessage - where TThirdMessage : INetworkMessage - { - WaitForMessagesReceivedWithTimeTravel(new List - { - typeof(TFirstMessage), - typeof(TSecondMessage), - typeof(TThirdMessage), - }, m_ClientNetworkManagers.ToList(), ReceiptType.Received); - } - - private void WaitForAllClientsToReceive() - where TFirstMessage : INetworkMessage - where TSecondMessage : INetworkMessage - where TThirdMessage : INetworkMessage - where TFourthMessage : INetworkMessage - { - WaitForMessagesReceivedWithTimeTravel(new List - { - typeof(TFirstMessage), - typeof(TSecondMessage), - typeof(TThirdMessage), - typeof(TFourthMessage), - }, m_ClientNetworkManagers.ToList(), ReceiptType.Received); - } - - [Test] - public void WhenAnRpcArrivesBeforeASpawnArrives_ItIsDeferred() - { - SpawnClients(); - CatchSpawns(); - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - serverObject.GetComponent().SendTestClientRpc(); - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - AssertSpawnTriggerCountForObject(manager, serverObject); - } - } - - [Test] - public void WhenADespawnArrivesBeforeASpawnArrives_ItIsDeferred() - { - SpawnClients(); - CatchSpawns(); - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - serverObject.GetComponent().Despawn(false); - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - AssertSpawnTriggerCountForObject(manager, serverObject); - } - } - - [Test] - public void WhenAChangeOwnershipMessageArrivesBeforeASpawnArrives_ItIsDeferred() - { - SpawnClients(); - CatchSpawns(); - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - WaitForAllClientsToReceive(); - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - AssertSpawnTriggerCountForObject(manager, serverObject); - } - } - - [Test] - public void WhenANetworkVariableDeltaMessageArrivesBeforeASpawnArrives_ItIsDeferred() - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - - - var serverObject = Object.Instantiate(m_NetworkVariablePrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - serverObject.GetComponent().TestNetworkVariable.Value = 1; - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - // TODO: Network Variables generate an extra message immediately at spawn for some reason... - // Seems like a bug since the network variable data is in the spawn message already. - AssertSpawnTriggerCountForObject(manager, serverObject, 1); - } - } - - [Test] - //[Ignore("Disabling this temporarily until it is migrated into new integration test.")] - public void WhenASpawnMessageArrivesBeforeThePrefabIsAvailable_ItIsDeferred() - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - Assert.AreEqual(1, manager.DeferredMessageCountTotal()); - Assert.AreEqual(0, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab, serverObject.GetComponent().GlobalObjectIdHash)); - - var component = GetComponentForClient(client.LocalClientId); - Assert.IsNull(component); - } - } - - [Test] - public void WhenAnRpcIsDeferred_ItIsProcessedOnSpawn() - { - WhenAnRpcArrivesBeforeASpawnArrives_ItIsDeferred(); - ReleaseSpawns(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - var component = GetComponentForClient(client.LocalClientId); - Assert.IsTrue(component.ClientRpcCalled); - } - } - - [Test] - public void WhenADespawnIsDeferred_ItIsProcessedOnSpawn() - { - WhenADespawnArrivesBeforeASpawnArrives_ItIsDeferred(); - ReleaseSpawns(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - // Should have been immediately despawned. - var component = GetComponentForClient(client.LocalClientId); - Assert.IsTrue(!component); - } - } - - [Test] - public void WhenAChangeOwnershipMessageIsDeferred_ItIsProcessedOnSpawn() - { - WhenAChangeOwnershipMessageArrivesBeforeASpawnArrives_ItIsDeferred(); - ReleaseSpawns(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - var component = GetComponentForClient(client.LocalClientId); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, component.OwnerClientId); - } - } - - [Test] - public void WhenANetworkVariableDeltaMessageIsDeferred_ItIsProcessedOnSpawn() - { - WhenANetworkVariableDeltaMessageArrivesBeforeASpawnArrives_ItIsDeferred(); - - foreach (var client in m_ClientNetworkManagers) - { - AddPrefabsToClient(client); - } - - ReleaseSpawns(); - - // Wait for the clients to spawn the NetworkObjects - bool HaveAllClientsSpawned() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!DeferredMessageTestNetworkVariableComponent.ClientInstances.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - WaitForConditionOrTimeOutWithTimeTravel(HaveAllClientsSpawned); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - var component = GetComponentForClient(client.LocalClientId); - Assert.AreEqual(1, component.TestNetworkVariable.Value); - } - } - - [Test] - public void WhenASpawnMessageIsDeferred_ItIsProcessedOnAddPrefab() - { - // This will prevent spawned clients from adding prefabs - m_SkipAddingPrefabsToClient = true; - WhenASpawnMessageArrivesBeforeThePrefabIsAvailable_ItIsDeferred(); - - // Now add the prefabs - foreach (var client in m_ClientNetworkManagers) - { - AddPrefabsToClient(client); - } - - // Wait for the clients to spawn the NetworkObjects - bool HaveAllClientsSpawned() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!DeferredMessageTestRpcComponent.ClientInstances.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - WaitForConditionOrTimeOutWithTimeTravel(HaveAllClientsSpawned); - - // Validate this test - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - var component = GetComponentForClient(client.LocalClientId); - Assert.IsNotNull(component); - } - } - - [Test] - public void WhenMultipleSpawnTriggeredMessagesAreDeferred_TheyAreAllProcessedOnSpawn() - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - - var serverObject = Object.Instantiate(m_RpcAndNetworkVariablePrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - serverObject.GetComponent().SendTestClientRpc(); - serverObject.GetComponent().TestNetworkVariable.Value = 1; - - WaitForAllClientsToReceive(); - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - - Assert.AreEqual(3, manager.DeferredMessageCountTotal()); - Assert.AreEqual(3, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(0, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab)); - AddPrefabsToClient(client); - } - - ReleaseSpawns(); - - // Wait for the clients to spawn the NetworkObjects - bool HaveAllClientsSpawned() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!DeferredMessageTestRpcAndNetworkVariableComponent.ClientInstances.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - WaitForConditionOrTimeOutWithTimeTravel(HaveAllClientsSpawned); - TimeTravel(0.1, 1); - - // Validate the spawned objects - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled, "Process triggers were not called!"); - Assert.AreEqual(0, manager.DeferredMessageCountTotal(), $"Deferred message count ({manager.DeferredMessageCountTotal()}) is not zero!"); - - var component = GetComponentForClient(client.LocalClientId); - Assert.IsTrue(component.ClientRpcCalled, "Client RPC was not called!"); - Assert.AreEqual(1, component.TestNetworkVariable.Value, $"Test {nameof(NetworkVariable)} ({component.TestNetworkVariable.Value}) does not equal 1!"); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, component.OwnerClientId, $"{component.name} owner id ({component.OwnerClientId}) does not equal first client id ({m_ClientNetworkManagers[0].LocalClientId})"); - } - } - - [Test] - public void WhenMultipleAddPrefabTriggeredMessagesAreDeferred_TheyAreAllProcessedOnAddNetworkPrefab() - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - - var serverObject2 = Object.Instantiate(m_RpcPrefab); - serverObject2.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject2.GetComponent().Spawn(); - - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - - Assert.AreEqual(2, manager.DeferredMessageCountTotal()); - Assert.AreEqual(0, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(2, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab)); - Assert.AreEqual(2, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab, serverObject.GetComponent().GlobalObjectIdHash)); - AddPrefabsToClient(client); - } - - // Wait for the clients to spawn the NetworkObjects - bool HaveAllClientsSpawned() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!DeferredMessageTestRpcComponent.ClientInstances.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - WaitForConditionOrTimeOutWithTimeTravel(HaveAllClientsSpawned); - - - foreach (var client in m_ClientNetworkManagers) - { - var found1 = false; - var found2 = false; -#if UNITY_2023_1_OR_NEWER - var deferredMessageTestRpcComponents = Object.FindObjectsByType(FindObjectsSortMode.None); -#else - var deferredMessageTestRpcComponents = Object.FindObjectsOfType(); -#endif - - foreach (var component in deferredMessageTestRpcComponents) - { - if (component.IsSpawned && component.NetworkManager.LocalClientId == client.LocalClientId) - { - if (component.NetworkObjectId == serverObject.GetComponent().NetworkObjectId) - { - found1 = true; - } - else if (component.NetworkObjectId == serverObject2.GetComponent().NetworkObjectId) - { - found2 = true; - } - } - } - - Assert.IsTrue(found1); - Assert.IsTrue(found2); - - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled); - - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - } - } - - [Test] - public void WhenSpawnTriggeredMessagesAreDeferredBeforeThePrefabIsAdded_AddingThePrefabCausesThemToBeProcessed() - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - - var serverObject = Object.Instantiate(m_RpcAndNetworkVariablePrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - - serverObject.GetComponent().SendTestClientRpc(); - serverObject.GetComponent().TestNetworkVariable.Value = 1; - // TODO: Remove this if we figure out how to work around the NetworkVariableDeltaMessage.Serialized issue at line 59 - // Otherwise, we have to wait for at least 1 tick for the NetworkVariableDeltaMessage to be generated before changing ownership - WaitForAllClientsToReceive(); - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForAllClientsToReceive(); - - // Validate messages are deferred and pending - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.DeferMessageCalled); - Assert.IsFalse(manager.ProcessTriggersCalled); - - Assert.AreEqual(4, manager.DeferredMessageCountTotal()); - - Assert.AreEqual(3, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnAddPrefab, serverObject.GetComponent().GlobalObjectIdHash)); - AddPrefabsToClient(client); - } - - // Wait for the clients to spawn the NetworkObjects - bool HaveAllClientsSpawned() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!DeferredMessageTestRpcAndNetworkVariableComponent.ClientInstances.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - WaitForConditionOrTimeOutWithTimeTravel(HaveAllClientsSpawned); - - TimeTravel(0.1, 1); - - // Validate the test - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.IsTrue(manager.ProcessTriggersCalled); - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - - var component = GetComponentForClient(client.LocalClientId); - Assert.NotNull(component); - Assert.IsTrue(component.ClientRpcCalled); - Assert.AreEqual(1, component.TestNetworkVariable.Value); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, component.OwnerClientId); - } - } - - [Test] - public void WhenAMessageIsDeferredForMoreThanTheConfiguredTime_ItIsRemoved([Values(1, 2, 3)] int timeout) - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = timeout; - } - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - var start = 0f; - - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforeDeferDelegate beforeDefer = (manager, key) => - { - if (start == 0) - { - start = client.RealTimeProvider.RealTimeSinceStartup; - } - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforeDefer = beforeDefer; - } - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForAllClientsToReceive(); - - foreach (var unused in m_ClientNetworkManagers) - { - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - } - - int purgeCount = 0; - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforePurgeDelegate beforePurge = (manager, key) => - { - ++purgeCount; - var elapsed = client.RealTimeProvider.RealTimeSinceStartup - start; - VerboseDebug(client.RealTimeProvider.GetType().FullName); - Assert.GreaterOrEqual(elapsed, timeout); - Assert.AreEqual(1, manager.DeferredMessageCountTotal()); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, key)); - Assert.AreEqual(serverObject.GetComponent().NetworkObjectId, key); - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = beforePurge; - } - - TimeTravel(timeout - 0.01, 1); - - bool HaveAnyClientsPurged() - { - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - if (manager.DeferredMessageCountTotal() == 0) - { - return true; - } - } - return false; - } - bool HaveAllClientsPurged() - { - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - if (manager.DeferredMessageCountTotal() != 0) - { - return false; - } - } - return true; - } - - Assert.IsFalse(HaveAnyClientsPurged()); - - TimeTravel(0.02, 1); - - Assert.IsTrue(HaveAllClientsPurged()); - } - - [Test] - public void WhenMultipleMessagesForTheSameObjectAreDeferredForMoreThanTheConfiguredTime_TheyAreAllRemoved([Values(1, 2, 3)] int timeout) - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = timeout; - } - var serverObject = Object.Instantiate(m_RpcAndNetworkVariablePrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - var start = 0f; - - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforeDeferDelegate beforeDefer = (manager, key) => - { - if (start == 0) - { - start = client.RealTimeProvider.RealTimeSinceStartup; - } - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforeDefer = beforeDefer; - } - - serverObject.GetComponent().SendTestClientRpc(); - serverObject.GetComponent().TestNetworkVariable.Value = 1; - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForMessagesReceivedWithTimeTravel( - new List {typeof(ClientRpcMessage), typeof(NetworkVariableDeltaMessage), typeof(ChangeOwnershipMessage), - }, m_ClientNetworkManagers.ToList(), ReceiptType.Received); - - foreach (var unused in m_ClientNetworkManagers) - { - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - } - - int purgeCount = 0; - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforePurgeDelegate beforePurge = (manager, key) => - { - ++purgeCount; - var elapsed = client.RealTimeProvider.RealTimeSinceStartup - start; - Assert.GreaterOrEqual(elapsed, timeout); - Assert.AreEqual(3, manager.DeferredMessageCountTotal()); - Assert.AreEqual(3, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, key)); - Assert.AreEqual(serverObject.GetComponent().NetworkObjectId, key); - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = beforePurge; - } - - var timePassedSinceFirstStart = MockTimeProvider.StaticRealTimeSinceStartup - start; - TimeTravel(timeout - 0.01 - timePassedSinceFirstStart, 1); - - bool HaveAnyClientsPurged() - { - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - if (manager.DeferredMessageCountTotal() == 0) - { - return true; - } - } - return false; - } - bool HaveAllClientsPurged() - { - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - if (manager.DeferredMessageCountTotal() != 0) - { - return false; - } - } - return true; - } - - Assert.IsFalse(HaveAnyClientsPurged()); - - TimeTravel(0.02 + timePassedSinceFirstStart, 1); - - Assert.IsTrue(HaveAllClientsPurged()); - } - - [Test] - public void WhenMultipleMessagesForDifferentObjectsAreDeferredForMoreThanTheConfiguredTime_TheyAreAllRemoved([Values(1, 2, 3)] int timeout) - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = timeout; - } - var serverObject = Object.Instantiate(m_RpcAndNetworkVariablePrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - - var serverObject2 = Object.Instantiate(m_RpcAndNetworkVariablePrefab); - serverObject2.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject2.GetComponent().Spawn(); - - WaitForClientsToCatchSpawns(2); - - var start = 0f; - - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforeDeferDelegate beforeDefer = (manager, key) => - { - if (start == 0) - { - start = client.RealTimeProvider.RealTimeSinceStartup; - } - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforeDefer = beforeDefer; - } - - serverObject.GetComponent().SendTestClientRpc(); - serverObject.GetComponent().TestNetworkVariable.Value = 1; - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - serverObject2.GetComponent().SendTestClientRpc(); - serverObject2.GetComponent().TestNetworkVariable.Value = 1; - serverObject2.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForMessagesReceivedWithTimeTravel( - new List {typeof(ClientRpcMessage), typeof(NetworkVariableDeltaMessage), typeof(ChangeOwnershipMessage),typeof(ClientRpcMessage), typeof(NetworkVariableDeltaMessage), typeof(ChangeOwnershipMessage), - }, m_ClientNetworkManagers.ToList(), ReceiptType.Received); - - foreach (var unused in m_ClientNetworkManagers) - { - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject2.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - } - - int purgeCount = 0; - foreach (var client in m_ClientNetworkManagers) - { - var remainingMessagesTotalThisClient = 6; - TestDeferredMessageManager.BeforePurgeDelegate beforePurge = (manager, key) => - { - ++purgeCount; - var elapsed = client.RealTimeProvider.RealTimeSinceStartup - start; - Assert.GreaterOrEqual(elapsed, timeout - 0.25f); - Assert.AreEqual(remainingMessagesTotalThisClient, manager.DeferredMessageCountTotal()); - Assert.AreEqual(remainingMessagesTotalThisClient, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, key)); - remainingMessagesTotalThisClient -= 3; - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = beforePurge; - } - - TimeTravel(timeout + 0.1f, 1); - foreach (var client in m_ClientNetworkManagers) - { - AddPrefabsToClient(client); - } - Assert.AreEqual(m_NumberOfClientsToLateJoin * 2, purgeCount); - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - } - } - - [Test] - public void WhenADeferredMessageIsRemoved_OtherMessagesForSameObjectAreRemoved([Values(1, 2, 3)] int timeout) - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = timeout; - } - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(); - - var start = 0f; - - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforeDeferDelegate beforeDefer = (manager, key) => - { - if (start == 0) - { - start = client.RealTimeProvider.RealTimeSinceStartup; - } - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforeDefer = beforeDefer; - } - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForAllClientsToReceive(); - - TimeTravel(timeout - 0.5f, 1); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(1, manager.DeferredMessageCountTotal()); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - } - - serverObject.GetComponent().ChangeOwnership(m_ServerNetworkManager.LocalClientId); - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(2, manager.DeferredMessageCountTotal()); - Assert.AreEqual(2, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(2, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - } - - foreach (var unused in m_ClientNetworkManagers) - { - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - } - - int purgeCount = 0; - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforePurgeDelegate beforePurge = (manager, key) => - { - ++purgeCount; - var elapsed = client.RealTimeProvider.RealTimeSinceStartup - start; - Assert.GreaterOrEqual(elapsed, timeout - 0.05f); - Assert.AreEqual(2, manager.DeferredMessageCountTotal()); - Assert.AreEqual(2, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(2, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, key)); - Assert.AreEqual(serverObject.GetComponent().NetworkObjectId, key); - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = beforePurge; - } - - foreach (var client in m_ClientNetworkManagers) - { - AddPrefabsToClient(client); - } - - TimeTravel(0.6f, 1); - - Assert.AreEqual(m_NumberOfClientsToLateJoin, purgeCount); - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(0, manager.DeferredMessageCountTotal()); - } - } - - [Test] - public void WhenADeferredMessageIsRemoved_OtherMessagesForDifferentObjectsAreNotRemoved([Values(1, 2, 3)] int timeout) - { - m_SkipAddingPrefabsToClient = true; - SpawnClients(); - CatchSpawns(); - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.SpawnTimeout = timeout; - } - var serverObject = Object.Instantiate(m_RpcPrefab); - serverObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject.GetComponent().Spawn(); - var serverObject2 = Object.Instantiate(m_RpcPrefab); - serverObject2.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - serverObject2.GetComponent().Spawn(); - WaitForClientsToCatchSpawns(2); - - var start = 0f; - - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforeDeferDelegate beforeDefer = (manager, key) => - { - if (start == 0) - { - start = client.RealTimeProvider.RealTimeSinceStartup; - } - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforeDefer = beforeDefer; - } - - serverObject.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - WaitForAllClientsToReceive(); - - TimeTravel(timeout - 0.5f, 1); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(1, manager.DeferredMessageCountTotal()); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(0, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject2.GetComponent().NetworkObjectId)); - } - - // KITTY-TODO: Review this change please: - // Changing ownership when the owner specified is already an owner should not send any messages - // The original test was changing ownership to the server when the object was spawned with the server being an owner. - //serverObject2.GetComponent().ChangeOwnership(m_ServerNetworkManager.LocalClientId); - serverObject2.GetComponent().ChangeOwnership(m_ClientNetworkManagers[1].LocalClientId); - WaitForAllClientsToReceive(); - - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(2, manager.DeferredMessageCountTotal()); - Assert.AreEqual(2, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject2.GetComponent().NetworkObjectId)); - } - - foreach (var unused in m_ClientNetworkManagers) - { - LogAssert.Expect(LogType.Warning, $"[Netcode] Deferred messages were received for a trigger of type {IDeferredNetworkMessageManager.TriggerType.OnSpawn} associated with id ({serverObject.GetComponent().NetworkObjectId}), but the {nameof(NetworkObject)} was not received within the timeout period {timeout} second(s)."); - } - - int purgeCount = 0; - foreach (var client in m_ClientNetworkManagers) - { - TestDeferredMessageManager.BeforePurgeDelegate beforePurge = (manager, key) => - { - ++purgeCount; - var elapsed = client.RealTimeProvider.RealTimeSinceStartup - start; - Assert.GreaterOrEqual(elapsed, timeout - 0.05f); - Assert.AreEqual(2, manager.DeferredMessageCountTotal()); - Assert.AreEqual(2, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject2.GetComponent().NetworkObjectId)); - - Assert.AreEqual(serverObject.GetComponent().NetworkObjectId, key); - }; - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = beforePurge; - } - - foreach (var client in m_ClientNetworkManagers) - { - AddPrefabsToClient(client); - } - - TimeTravel(0.6f, 1); - - Assert.AreEqual(m_NumberOfClientsToLateJoin, purgeCount); - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - Assert.AreEqual(1, manager.DeferredMessageCountTotal()); - Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredNetworkMessageManager.TriggerType.OnSpawn)); - Assert.AreEqual(0, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject.GetComponent().NetworkObjectId)); - Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredNetworkMessageManager.TriggerType.OnSpawn, serverObject2.GetComponent().NetworkObjectId)); - } - foreach (var client in m_ClientNetworkManagers) - { - var manager = (TestDeferredMessageManager)client.DeferredMessageManager; - manager.OnBeforePurge = null; - } - } - } -} diff --git a/Tests/Runtime/DeferredMessagingTests.cs.meta b/Tests/Runtime/DeferredMessagingTests.cs.meta deleted file mode 100644 index 7dff7f8..0000000 --- a/Tests/Runtime/DeferredMessagingTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b3d771dc2a334464ad96e8c66ac776cc -timeCreated: 1650295945 \ No newline at end of file diff --git a/Tests/Runtime/DisconnectTests.cs b/Tests/Runtime/DisconnectTests.cs deleted file mode 100644 index af00165..0000000 --- a/Tests/Runtime/DisconnectTests.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Validates the client disconnection process. - /// This assures that: - /// - When a client disconnects from the server that the server: - /// -- Detects the client disconnected. - /// -- Cleans up the transport to NGO client (and vice versa) mappings. - /// - When a server disconnects a client that: - /// -- The client detects this disconnection. - /// -- The server cleans up the transport to NGO client (and vice versa) mappings. - /// - When the server-side player object is destroyed - /// - When the server-side player object ownership is transferred back to the server - /// - [TestFixture(OwnerPersistence.DestroyWithOwner)] - [TestFixture(OwnerPersistence.DontDestroyWithOwner)] - internal class DisconnectTests : NetcodeIntegrationTest - { - public enum OwnerPersistence - { - DestroyWithOwner, - DontDestroyWithOwner - } - - public enum ClientDisconnectType - { - ServerDisconnectsClient, - ClientDisconnectsFromServer - } - - protected override int NumberOfClients => 1; - - private OwnerPersistence m_OwnerPersistence; - private ClientDisconnectType m_ClientDisconnectType; - private bool m_ClientDisconnected; - private Dictionary m_DisconnectedEvent = new Dictionary(); - private ulong m_DisconnectEventClientId; - private ulong m_TransportClientId; - private ulong m_ClientId; - - - public DisconnectTests(OwnerPersistence ownerPersistence) - { - m_OwnerPersistence = ownerPersistence; - } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.GetComponent().DontDestroyWithOwner = m_OwnerPersistence == OwnerPersistence.DontDestroyWithOwner; - base.OnCreatePlayerPrefab(); - } - - protected override void OnServerAndClientsCreated() - { - // Adjusting client and server timeout periods to reduce test time - // Get the tick frequency in milliseconds and triple it for the heartbeat timeout - var heartBeatTimeout = (int)(300 * (1.0f / m_ServerNetworkManager.NetworkConfig.TickRate)); - var unityTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport; - if (unityTransport != null) - { - unityTransport.HeartbeatTimeoutMS = heartBeatTimeout; - } - - unityTransport = m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport; - if (unityTransport != null) - { - unityTransport.HeartbeatTimeoutMS = heartBeatTimeout; - } - - base.OnServerAndClientsCreated(); - } - - protected override IEnumerator OnSetup() - { - m_ClientDisconnected = false; - m_ClientId = 0; - m_TransportClientId = 0; - return base.OnSetup(); - } - - /// - /// Used to detect the client disconnected on the server side - /// - private void OnClientDisconnectCallback(ulong obj) - { - m_ClientDisconnected = true; - } - - private void OnConnectionEvent(NetworkManager networkManager, ConnectionEventData connectionEventData) - { - if (connectionEventData.EventType != ConnectionEvent.ClientDisconnected) - { - return; - } - - m_DisconnectedEvent.Add(networkManager, connectionEventData); - } - - /// - /// Conditional check to assure the transport to client (and vice versa) mappings are cleaned up - /// - private bool TransportIdCleanedUp() - { - if (m_ServerNetworkManager.ConnectionManager.TransportIdToClientId(m_TransportClientId) == m_ClientId) - { - return false; - } - - if (m_ServerNetworkManager.ConnectionManager.ClientIdToTransportId(m_ClientId) == m_TransportClientId) - { - return false; - } - return true; - } - - /// - /// Conditional check to make sure the client player object no longer exists on the server side - /// - private bool DoesServerStillHaveSpawnedPlayerObject() - { - if (m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_ClientId)) - { - var playerObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientId]; - if (playerObject != null && playerObject.IsSpawned) - { - return false; - } - } - return !m_ServerNetworkManager.SpawnManager.SpawnedObjects.Any(x => x.Value.IsPlayerObject && x.Value.OwnerClientId == m_ClientId); - } - - [UnityTest] - public IEnumerator ClientPlayerDisconnected([Values] ClientDisconnectType clientDisconnectType) - { - m_ClientId = m_ClientNetworkManagers[0].LocalClientId; - m_ClientDisconnectType = clientDisconnectType; - - var serverSideClientPlayer = m_ServerNetworkManager.ConnectionManager.ConnectedClients[m_ClientId].PlayerObject; - - m_TransportClientId = m_ServerNetworkManager.ConnectionManager.ClientIdToTransportId(m_ClientId); - - if (clientDisconnectType == ClientDisconnectType.ServerDisconnectsClient) - { - m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback; - m_ClientNetworkManagers[0].OnConnectionEvent += OnConnectionEvent; - m_ServerNetworkManager.OnConnectionEvent += OnConnectionEvent; - m_ServerNetworkManager.DisconnectClient(m_ClientId); - } - else - { - m_ServerNetworkManager.OnClientDisconnectCallback += OnClientDisconnectCallback; - m_ServerNetworkManager.OnConnectionEvent += OnConnectionEvent; - m_ClientNetworkManagers[0].OnConnectionEvent += OnConnectionEvent; - - yield return StopOneClient(m_ClientNetworkManagers[0]); - } - - yield return WaitForConditionOrTimeOut(() => m_ClientDisconnected); - AssertOnTimeout("Timed out waiting for client to disconnect!"); - - if (clientDisconnectType == ClientDisconnectType.ServerDisconnectsClient) - { - Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ServerNetworkManager), $"Could not find the server {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent[m_ServerNetworkManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the server {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ClientNetworkManagers[0]), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent[m_ClientNetworkManagers[0]].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!"); - // Unregister for this event otherwise it will be invoked during teardown - m_ServerNetworkManager.OnConnectionEvent -= OnConnectionEvent; - } - else - { - Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ServerNetworkManager), $"Could not find the server {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent[m_ServerNetworkManager].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the server {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ClientNetworkManagers[0]), $"Could not find the client {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent[m_ClientNetworkManagers[0]].ClientId == m_ClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the client {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Count == 1, $"Expected connected client identifiers count to be 1 but it was {m_ServerNetworkManager.ConnectedClientsIds.Count}!"); - Assert.IsTrue(m_ServerNetworkManager.ConnectedClients.Count == 1, $"Expected connected client identifiers count to be 1 but it was {m_ServerNetworkManager.ConnectedClients.Count}!"); - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsList.Count == 1, $"Expected connected client identifiers count to be 1 but it was {m_ServerNetworkManager.ConnectedClientsList.Count}!"); - } - - if (m_OwnerPersistence == OwnerPersistence.DestroyWithOwner) - { - // When we are destroying with the owner, validate the player object is destroyed on the server side - yield return WaitForConditionOrTimeOut(DoesServerStillHaveSpawnedPlayerObject); - AssertOnTimeout("Timed out waiting for client's player object to be destroyed!"); - } - else - { - // When we are not destroying with the owner, ensure the player object's ownership was transferred back to the server - yield return WaitForConditionOrTimeOut(() => serverSideClientPlayer.IsOwnedByServer); - AssertOnTimeout("The client's player object's ownership was not transferred back to the server!"); - } - - yield return WaitForConditionOrTimeOut(TransportIdCleanedUp); - AssertOnTimeout("Timed out waiting for transport and client id mappings to be cleaned up!"); - - // Validate the host-client generates a OnClientDisconnected event when it shutsdown. - // Only test when the test run is the client disconnecting from the server (otherwise the server will be shutdown already) - if (clientDisconnectType == ClientDisconnectType.ClientDisconnectsFromServer) - { - m_DisconnectedEvent.Clear(); - m_ClientDisconnected = false; - m_ServerNetworkManager.Shutdown(); - - yield return WaitForConditionOrTimeOut(() => m_ClientDisconnected); - AssertOnTimeout("Timed out waiting for host-client to generate disconnect message!"); - - Assert.IsTrue(m_DisconnectedEvent.ContainsKey(m_ServerNetworkManager), $"Could not find the server {nameof(NetworkManager)} disconnect event entry!"); - Assert.IsTrue(m_DisconnectedEvent[m_ServerNetworkManager].ClientId == NetworkManager.ServerClientId, $"Expected ClientID {m_ClientId} but found ClientID {m_DisconnectedEvent[m_ServerNetworkManager].ClientId} for the server {nameof(NetworkManager)} disconnect event entry!"); - } - } - } -} diff --git a/Tests/Runtime/DisconnectTests.cs.meta b/Tests/Runtime/DisconnectTests.cs.meta deleted file mode 100644 index 5528fb9..0000000 --- a/Tests/Runtime/DisconnectTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b05b4daca3854ff6b01a1f002d433dd6 -timeCreated: 1631652586 \ No newline at end of file diff --git a/Tests/Runtime/DistributedAuthority.meta b/Tests/Runtime/DistributedAuthority.meta deleted file mode 100644 index ee02283..0000000 --- a/Tests/Runtime/DistributedAuthority.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 421e3306c97e10f47b9efb6101a998ee -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs b/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs deleted file mode 100644 index faba405..0000000 --- a/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs +++ /dev/null @@ -1,266 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class DeferredDespawningTests : IntegrationTestWithApproximation - { - private const int k_DaisyChainedCount = 5; - protected override int NumberOfClients => 2; - private List m_DaisyChainedDespawnObjects = new List(); - private List m_HasReachedEnd = new List(); - - public DeferredDespawningTests() : base(HostOrServer.DAHost) - { - } - - protected override void OnServerAndClientsCreated() - { - var daisyChainPrevious = (DeferredDespawnDaisyChained)null; - for (int i = 0; i < k_DaisyChainedCount; i++) - { - var daisyChainNode = CreateNetworkObjectPrefab($"Daisy-{i}"); - var daisyChainBehaviour = daisyChainNode.AddComponent(); - daisyChainBehaviour.IsRoot = i == 0; - if (daisyChainPrevious != null) - { - daisyChainPrevious.PrefabToSpawnWhenDespawned = daisyChainBehaviour.gameObject; - } - m_DaisyChainedDespawnObjects.Add(daisyChainNode); - - daisyChainPrevious = daisyChainBehaviour; - } - - base.OnServerAndClientsCreated(); - } - - - - [UnityTest] - public IEnumerator DeferredDespawning() - { - DeferredDespawnDaisyChained.EnableVerbose = m_EnableVerboseDebug; - var rootInstance = SpawnObject(m_DaisyChainedDespawnObjects[0], m_ServerNetworkManager); - DeferredDespawnDaisyChained.ReachedLastChainInstance = ReachedLastChainObject; - var timeoutHelper = new TimeoutHelper(300); - yield return WaitForConditionOrTimeOut(HaveAllClientsReachedEndOfChain, timeoutHelper); - AssertOnTimeout($"Timed out waiting for all children to reach the end of their chained deferred despawns!", timeoutHelper); - } - - private bool HaveAllClientsReachedEndOfChain() - { - if (!m_HasReachedEnd.Contains(m_ServerNetworkManager.LocalClientId)) - { - return false; - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!m_HasReachedEnd.Contains(client.LocalClientId)) - { - return false; - } - } - return true; - } - - private void ReachedLastChainObject(ulong clientId) - { - m_HasReachedEnd.Add(clientId); - } - } - - /// - /// This helper behaviour handles the majority of the validation for deferred despawning. - /// Each instance triggers a series of deferred despawns where the owner validates the - /// NetworkVariables are updated and spawns another prefab prior to despawning locally - /// and the non-owners validate receiving the NetworkVariable change notification which - /// contains a reference to a DeferredDespawnDaisyChained component on the newly spawned - /// prefab driven by the authority. This repeats for the number specified in the integration - /// test. - /// - internal class DeferredDespawnDaisyChained : NetworkBehaviour - { - public static bool EnableVerbose; - public static Action ReachedLastChainInstance; - private const int k_StartingDeferTick = 4; - public static Dictionary> ClientRelativeInstances = new Dictionary>(); - public bool IsRoot; - public GameObject PrefabToSpawnWhenDespawned; - public bool WasContactedByPeviousChainMember { get; private set; } - public int DeferDespawnTick { get; private set; } - - private void PingInstance() - { - WasContactedByPeviousChainMember = true; - } - - /// - /// This hits two birds with one NetworkVariable: - /// - Validates that NetworkVariables modified while the authority is in the middle of deferring a despawn are serialized and received by non-authority instances. - /// - Validates that the non-authority instances receive the updates within the deferred tick period of time and can use them to handle other visual synchronization - /// realted tasks (or the like). - /// - private NetworkVariable m_ValidateDirtyNetworkVarUpdate = new NetworkVariable(); - - private DeferredDespawnDaisyChained m_NextNodeSpawned = null; - - private void FailTest(string msg) - { - Assert.Fail($"[{nameof(DeferredDespawnDaisyChained)}][Client-{NetworkManager.LocalClientId}] {msg}"); - } - - public override void OnNetworkSpawn() - { - var localId = NetworkManager.LocalClientId; - if (!ClientRelativeInstances.ContainsKey(localId)) - { - ClientRelativeInstances.Add(localId, new Dictionary()); - } - - if (ClientRelativeInstances[localId].ContainsKey(NetworkObject.NetworkObjectId)) - { - FailTest($"[{nameof(OnNetworkSpawn)}] Client already has a table entry for NetworkObject-{NetworkObject.NetworkObjectId} | {name}!"); - } - - ClientRelativeInstances[localId].Add(NetworkObject.NetworkObjectId, this); - - if (!HasAuthority) - { - m_ValidateDirtyNetworkVarUpdate.OnValueChanged += OnValidateDirtyChanged; - } - - if (HasAuthority && IsRoot) - { - DeferDespawnTick = k_StartingDeferTick; - } - - base.OnNetworkSpawn(); - } - - private void OnValidateDirtyChanged(NetworkBehaviourReference previous, NetworkBehaviourReference current) - { - if (!HasAuthority) - { - if (!current.TryGet(out m_NextNodeSpawned, NetworkManager)) - { - FailTest($"[{nameof(OnValidateDirtyChanged)}][{nameof(NetworkBehaviourReference)}] Failed to get the {nameof(DeferredDespawnDaisyChained)} behaviour from the {nameof(NetworkBehaviourReference)}!"); - } - - if (m_NextNodeSpawned.NetworkManager != NetworkManager) - { - FailTest($"[{nameof(NetworkManager)}][{nameof(NetworkBehaviourReference.TryGet)}] The {nameof(NetworkManager)} of {nameof(m_NextNodeSpawned)} does not match the local relative {nameof(NetworkManager)} instance!"); - } - } - } - - public override void OnNetworkDespawn() - { - if (!HasAuthority && !NetworkManager.ShutdownInProgress) - { - if (PrefabToSpawnWhenDespawned != null) - { - m_NextNodeSpawned.PingInstance(); - } - else - { - ReachedLastChainInstance?.Invoke(NetworkManager.LocalClientId); - } - } - base.OnNetworkDespawn(); - } - - private void InvokeDespawn() - { - if (!HasAuthority) - { - FailTest($"[{nameof(InvokeDespawn)}] Client is not the authority but this was invoked (integration test logic issue)!"); - } - NetworkObject.DeferDespawn(DeferDespawnTick); - } - - public override void OnDeferringDespawn(int despawnTick) - { - if (!HasAuthority) - { - FailTest($"[{nameof(OnDeferringDespawn)}] Client is not the authority but this was invoked (integration test logic issue)!"); - } - - if (despawnTick != (DeferDespawnTick + NetworkManager.ServerTime.Tick)) - { - FailTest($"[{nameof(OnDeferringDespawn)}] The passed in {despawnTick} parameter ({despawnTick}) does not equal the expected value of ({DeferDespawnTick + NetworkManager.ServerTime.Tick})!"); - } - - if (PrefabToSpawnWhenDespawned != null) - { - var deferNetworkObject = PrefabToSpawnWhenDespawned.GetComponent().InstantiateAndSpawn(NetworkManager); - var deferComponent = deferNetworkObject.GetComponent(); - // Slowly increment the despawn tick count as we process the chain of deferred despawns - deferComponent.DeferDespawnTick = DeferDespawnTick + 1; - // This should get updated on all non-authority instances before they despawn - m_ValidateDirtyNetworkVarUpdate.Value = new NetworkBehaviourReference(deferComponent); - } - else - { - ReachedLastChainInstance?.Invoke(NetworkManager.LocalClientId); - } - base.OnDeferringDespawn(despawnTick); - } - - private bool m_DeferredDespawn; - private void Update() - { - if (!IsSpawned || !HasAuthority || m_DeferredDespawn) - { - return; - } - - // Wait until all clients have this instance - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (!ClientRelativeInstances.ContainsKey(clientId)) - { - // exit early if the client doesn't exist yet - return; - } - - if (!ClientRelativeInstances[clientId].ContainsKey(NetworkObjectId)) - { - // exit early if the client hasn't spawned a clone of this instance yet - return; - } - - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - - // This should happen shortly afte the instances spawns (based on the deferred despawn count) - if (!IsRoot && !ClientRelativeInstances[clientId][NetworkObjectId].WasContactedByPeviousChainMember) - { - // exit early if the non-authority instance has not been contacted yet - return; - } - } - - // If we made it here, then defer despawn this instance - InvokeDespawn(); - m_DeferredDespawn = true; - } - - private void Log(string message) - { - if (!EnableVerbose) - { - return; - } - Debug.Log($"[{name}][Client-{NetworkManager.LocalClientId}][{NetworkObjectId}] {message}"); - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs.meta b/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs.meta deleted file mode 100644 index e7d54c6..0000000 --- a/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c7b700919b058f446a75a398d5be9af4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs b/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs deleted file mode 100644 index 7957e6c..0000000 --- a/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs +++ /dev/null @@ -1,518 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.Transports.UTP; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Validates that distributable NetworkObjects are distributed upon - /// a client connecting or disconnecting. - /// - internal class DistributeObjectsTests : IntegrationTestWithApproximation - { - private GameObject m_DistributeObject; - - private StringBuilder m_ErrorLog = new StringBuilder(); - - private const int k_LateJoinClientCount = 4; - protected override int NumberOfClients => 0; - - public DistributeObjectsTests() : base(HostOrServer.DAHost) - { - } - - protected override IEnumerator OnSetup() - { - m_ObjectToValidate = null; - return base.OnSetup(); - } - - protected override void OnServerAndClientsCreated() - { - var serverTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as UnityTransport; - // I hate having to add time to our tests, but in case a VM is running slow the disconnect timeout needs to be reasonably high - serverTransport.DisconnectTimeoutMS = 1000; - m_DistributeObject = CreateNetworkObjectPrefab("DisObject"); - m_DistributeObject.AddComponent(); - m_DistributeObject.AddComponent(); - - // Set baseline to be distributable - var networkObject = m_DistributeObject.GetComponent(); - networkObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.Distributable); - networkObject.DontDestroyWithOwner = true; - base.OnServerAndClientsCreated(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - m_ServerNetworkManager.SpawnManager.EnableDistributeLogging = m_EnableVerboseDebug; - m_ServerNetworkManager.ConnectionManager.EnableDistributeLogging = m_EnableVerboseDebug; - return base.OnServerAndClientsConnected(); - } - - private NetworkObject m_ObjectToValidate; - - private bool ValidateObjectSpawnedOnAllClients() - { - m_ErrorLog.Clear(); - - var networkObjectId = m_ObjectToValidate.NetworkObjectId; - var name = m_ObjectToValidate.name; - if (!UseCMBService() && !m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) - { - m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} has not spawned {name}!"); - return false; - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!client.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) - { - m_ErrorLog.Append($"Client-{client.LocalClientId} has not spawned {name}!"); - return false; - } - } - return true; - } - - private const int k_ObjectCount = 20; - - private bool ValidateDistributedObjectsSpawned(bool lateJoining) - { - m_ErrorLog.Clear(); - var hostId = m_ServerNetworkManager.LocalClientId; - if (!DistributeObjectsTestHelper.DistributedObjects.ContainsKey(hostId)) - { - m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have an entry in the root of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - var daHostObjectTracking = DistributeObjectsTestHelper.DistributedObjects[hostId]; - if (!daHostObjectTracking.ContainsKey(hostId)) - { - m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have a local an entry in the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - - var daHostObjects = daHostObjectTracking[hostId]; - var expected = 0; - if (lateJoining) - { - expected = k_ObjectCount / (m_ClientNetworkManagers.Count() + 1); - } - else - { - expected = k_ObjectCount / (m_ClientNetworkManagers.Where((c) => c.IsConnectedClient).Count() + 1); - } - - // It should theoretically be the expected or... - if (daHostObjects.Count != expected) - { - // due to not rounding one more than the expected - expected++; - if (daHostObjects.Count != expected) - { - m_ErrorLog.AppendLine($"[Client-{hostId}][General] Expected {expected} spawned objects, but only {daHostObjects.Count} exist!"); - return false; - } - } - - foreach (var networkObject in daHostObjects) - { - m_ObjectToValidate = networkObject.Value; - if (!ValidateObjectSpawnedOnAllClients()) - { - m_ErrorLog.AppendLine($"[{m_ObjectToValidate.name}] Was not spawned on all clients!"); - return false; - } - } - return true; - } - - private bool ValidateOwnershipTablesMatch() - { - m_ErrorLog.Clear(); - var hostId = m_ServerNetworkManager.LocalClientId; - var expectedEntries = m_ClientNetworkManagers.Where((c) => c.IsListening && c.IsConnectedClient).Count() + 1; - // Make sure all clients have an table created - if (DistributeObjectsTestHelper.DistributedObjects.Count < expectedEntries) - { - m_ErrorLog.AppendLine($"[General] Expected {expectedEntries} entries in the root of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table but only {DistributeObjectsTestHelper.DistributedObjects.Count} exist!"); - return false; - } - - if (!DistributeObjectsTestHelper.DistributedObjects.ContainsKey(hostId)) - { - m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have an entry in the root of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[hostId]; - if (!daHostEntries.ContainsKey(hostId)) - { - m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have a local an entry in the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - var clients = m_ServerNetworkManager.ConnectedClientsIds.ToList(); - clients.Remove(0); - - // Cycle through each client's entry on the DAHost to run a comparison - foreach (var hostClientEntry in daHostEntries) - { - foreach (var ownerEntry in hostClientEntry.Value) - { - foreach (var client in clients) - { - var clientOwnerTable = DistributeObjectsTestHelper.DistributedObjects[client]; - if (!clientOwnerTable.ContainsKey(hostClientEntry.Key)) - { - m_ErrorLog.AppendLine($"[Client-{client}] No ownership table exists the client relative section of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - var clientEntry = clientOwnerTable[hostClientEntry.Key]; - if (!clientEntry.ContainsKey(ownerEntry.Key)) - { - m_ErrorLog.AppendLine($"[Client-{client}] {ownerEntry.Value.name} does not exists in Client-{client}'s sub-section for Owner-{hostClientEntry.Key} relative section of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!"); - return false; - } - var clientObjectEntry = clientEntry[ownerEntry.Key]; - if (clientObjectEntry.OwnerClientId != ownerEntry.Value.OwnerClientId) - { - m_ErrorLog.AppendLine($"[Client-{client}][Owner Mismatch] {clientObjectEntry.OwnerClientId} does equal {ownerEntry.Value.OwnerClientId}!"); - return false; - } - // Assure the observers match - foreach (var observer in ownerEntry.Value.Observers) - { - if (!clientObjectEntry.Observers.Contains(observer)) - { - m_ErrorLog.AppendLine($"[Client-{client}][Observer Mismatch] {nameof(NetworkObject)} {clientObjectEntry.name}'s observers does not contain {observer}, but the authority instance does!"); - return false; - } - } - } - } - } - return true; - } - - private bool ValidateTransformsMatch() - { - m_ErrorLog.Clear(); - var hostId = m_ServerNetworkManager.LocalClientId; - var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[hostId]; - var clients = m_ServerNetworkManager.ConnectedClientsIds.ToList(); - foreach (var clientOwner in daHostEntries.Keys) - { - // Cycle through the owner's objects - foreach (var entry in DistributeObjectsTestHelper.DistributedObjects[clientOwner][clientOwner].Values) - { - var ownerTestTransform = entry.GetComponent(); - // Compare against the other client instances of that object - foreach (var client in clients) - { - if (client == clientOwner) - { - continue; - } - - var clientObjectInstance = DistributeObjectsTestHelper.DistributedObjects[client][clientOwner][entry.NetworkObjectId]; - if (!ownerTestTransform.IsPositionClose(clientObjectInstance.transform.position)) - { - m_ErrorLog.AppendLine($"[Position Mismatch] Client-{client} Instance: {GetVector3Values(clientObjectInstance.transform.position)} != Owner Instance: {GetVector3Values(ownerTestTransform.transform.position)}!"); - return false; - } - } - } - } - return true; - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs; - base.OnNewClientCreated(networkManager); - } - - private bool SpawnCountsMatch() - { - var passed = true; - var spawnCount = 0; - m_ErrorLog.Clear(); - if (!UseCMBService()) - { - spawnCount = m_ServerNetworkManager.SpawnManager.SpawnedObjects.Count; - } - else - { - spawnCount = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects.Count; - } - foreach (var client in m_ClientNetworkManagers) - { - var clientCount = client.SpawnManager.SpawnedObjects.Count; - if (clientCount != spawnCount) - { - m_ErrorLog.AppendLine($"[Client-{client.LocalClientId}] Has a spawn count of {clientCount} but {spawnCount} was expected!"); - passed = false; - } - } - return passed; - } - - /// - /// This is a straight forward validation for the distribution of NetworkObjects - /// upon a client connecting or disconnecting. It also validates that the observers - /// on each non-authority instance matches the authority instance's. Finally, it - /// also includes validation that NetworkTransform updates continue to update and - /// synchronize properly after ownership for a set number of objects has changed. - /// - [UnityTest] - public IEnumerator DistributeNetworkObjects() - { - for (int i = 0; i < k_ObjectCount; i++) - { - SpawnObject(m_DistributeObject, m_ServerNetworkManager); - } - - // Validate NetworkObjects get redistributed properly when a client joins - for (int j = 0; j < k_LateJoinClientCount; j++) - { - yield return CreateAndStartNewClient(); - - yield return WaitForConditionOrTimeOut(() => ValidateDistributedObjectsSpawned(true)); - AssertOnTimeout($"[Client-{j + 1}][Initial Spawn] Not all clients spawned all objects!\n {m_ErrorLog}"); - - yield return WaitForConditionOrTimeOut(ValidateOwnershipTablesMatch); - AssertOnTimeout($"[Client-{j + 1}][OnwershipTable Mismatch] {m_ErrorLog}"); - - // When ownership changes, the new owner will randomly pick a new target to move towards and will move towards the target. - // Validate all other instances of the NetworkObjects that have had newly assigned owners have matching positions to the - // newly assigned owenr's instance. - yield return WaitForConditionOrTimeOut(ValidateTransformsMatch); - AssertOnTimeout($"[Client-{j + 1}][Transform Mismatch] {m_ErrorLog}"); - DisplayOwnership(); - - yield return WaitForConditionOrTimeOut(SpawnCountsMatch); - AssertOnTimeout($"[Spawn Count Mismatch] {m_ErrorLog}"); - } - - // Validate NetworkObjects get redistributed properly when a client disconnects - for (int j = k_LateJoinClientCount - 1; j >= 0; j--) - { - var client = m_ClientNetworkManagers[j]; - - // Remove the client from the other clients' ownership tracking table - DistributeObjectsTestHelper.RemoveClient(client.LocalClientId); - - // Disconnect the client - yield return StopOneClient(client, true); - - //yield return new WaitForSeconds(0.1f); - - // Validate all tables match - yield return WaitForConditionOrTimeOut(ValidateOwnershipTablesMatch); - - AssertOnTimeout($"[Client-{j + 1}][OnwershipTable Mismatch] {m_ErrorLog}"); - - // When ownership changes, the new owner will randomly pick a new target to move towards and will move towards the target. - // Validate all other instances of the NetworkObjects that have had newly assigned owners have matching positions to the - // newly assigned owenr's instance. - yield return WaitForConditionOrTimeOut(ValidateTransformsMatch); - AssertOnTimeout($"[Client-{j + 1}][Transform Mismatch] {m_ErrorLog}"); - - // DANGO-TODO: Make this tied to verbose mode once we know the CMB Service integration works properly - DisplayOwnership(); - - yield return WaitForConditionOrTimeOut(SpawnCountsMatch); - AssertOnTimeout($"[Spawn Count Mismatch] {m_ErrorLog}"); - } - } - - private void DisplayOwnership() - { - m_ErrorLog.Clear(); - var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[0]; - - foreach (var entry in daHostEntries) - { - m_ErrorLog.AppendLine($"[Client-{entry.Key}][Owned Objects: {entry.Value.Count}]"); - } - - VerboseDebug($"{m_ErrorLog}"); - } - - /// - /// This keeps track of each clients perspective of which NetworkObjects are owned by which client. - /// It is used to validate that all clients are in synch with ownership updates. - /// - internal class DistributeObjectsTestHelper : NetworkBehaviour - { - /// - /// [Client Context][Client Owners][NetworkObjectId][NetworkObject] - /// - public static Dictionary>> DistributedObjects = new Dictionary>>(); - - public static void RemoveClient(ulong clientId) - { - foreach (var clients in DistributedObjects.Values) - { - clients.Remove(clientId); - } - DistributedObjects.Remove(clientId); - } - - internal ulong ClientId; - - public override void OnNetworkSpawn() - { - ClientId = NetworkManager.LocalClientId; - UpdateOwnerTableAdd(); - base.OnNetworkSpawn(); - } - - private void UpdateOwnerTableAdd() - { - if (!DistributedObjects.ContainsKey(ClientId)) - { - DistributedObjects.Add(ClientId, new Dictionary>()); - } - if (!DistributedObjects[ClientId].ContainsKey(OwnerClientId)) - { - DistributedObjects[ClientId].Add(OwnerClientId, new Dictionary()); - } - - if (DistributedObjects[ClientId][OwnerClientId].ContainsKey(NetworkObject.NetworkObjectId)) - { - throw new Exception($"[Client-{ClientId}][{name}] {nameof(NetworkObject)} already exists in Client-{ClientId}'s " + - $"DistributedObjects being tracking under Client-{OwnerClientId}'s list of owned {nameof(NetworkObject)}s!"); - } - DistributedObjects[ClientId][OwnerClientId].Add(NetworkObject.NetworkObjectId, NetworkObject); - } - - private void UpdateOwnerTableRemove(ulong previous) - { - // This does not need to exist when first starting, but will (at one point in testing) - // become valid. - if (DistributedObjects[ClientId].ContainsKey(previous)) - { - if (DistributedObjects[ClientId][previous].ContainsKey(NetworkObject.NetworkObjectId)) - { - DistributedObjects[ClientId][previous].Remove(NetworkObject.NetworkObjectId); - } - } - } - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - // At start, if NetworkSpawn has not been completed the local client ignores this - if (!DistributedObjects.ContainsKey(ClientId)) - { - return; - } - UpdateOwnerTableRemove(previous); - UpdateOwnerTableAdd(); - base.OnOwnershipChanged(previous, current); - } - } - - /// - /// This is used to validate that upon distributed ownership changes NetworkTransform sycnhronization - /// still works properly. - /// - internal class DistributeTestTransform : NetworkTransform - { - private float m_DeltaVarPosition = 0.15f; - private float m_DeltaVarQauternion = 0.015f; - protected Vector3 GetRandomVector3(float min, float max, Vector3 baseLine, bool randomlyApplySign = false) - { - var retValue = new Vector3(baseLine.x * Random.Range(min, max), baseLine.y * Random.Range(min, max), baseLine.z * Random.Range(min, max)); - if (!randomlyApplySign) - { - return retValue; - } - - retValue.x *= Random.Range(1, 100) >= 50 ? -1 : 1; - retValue.y *= Random.Range(1, 100) >= 50 ? -1 : 1; - retValue.z *= Random.Range(1, 100) >= 50 ? -1 : 1; - return retValue; - } - - protected override bool OnIsServerAuthoritative() - { - var isOwnerAuth = base.OnIsServerAuthoritative(); - Assert.IsFalse(isOwnerAuth, $"Base {nameof(NetworkTransform)} did not automatically return false in distributed authority mode!"); - return isOwnerAuth; - } - - public override void OnNetworkSpawn() - { - base.OnNetworkSpawn(); - - if (CanCommitToTransform) - { - var randomPos = GetRandomVector3(1.0f, 10.0f, Vector3.one, true); - SetState(randomPos, null, null, false); - m_TargetPosition = randomPos; - } - } - - private Vector3 m_TargetPosition; - private Vector3 m_DirToTarget; - private bool m_ReachedTarget; - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - base.OnOwnershipChanged(previous, current); - m_TargetPosition = transform.position + GetRandomVector3(4.0f, 8.0f, Vector3.one, true); - m_DirToTarget = (m_TargetPosition - transform.position).normalized; - m_ReachedTarget = false; - } - - public override void OnUpdate() - { - if (CanCommitToTransform) - { - if (!m_ReachedTarget) - { - var distance = Vector3.Distance(transform.position, m_TargetPosition); - - var speed = Mathf.Clamp(distance, 0.10f, 2.0f); - - transform.position += m_DirToTarget * speed * Time.deltaTime; - - m_ReachedTarget = IsPositionClose(m_TargetPosition); - } - } - } - - public bool IsPositionClose(Vector3 position) - { - return Approximately(transform.position, position); - } - - protected bool Approximately(Vector3 a, Vector3 b) - { - var deltaVariance = m_DeltaVarPosition; - return Math.Round(Mathf.Abs(a.x - b.x), 2) <= deltaVariance && - Math.Round(Mathf.Abs(a.y - b.y), 2) <= deltaVariance && - Math.Round(Mathf.Abs(a.z - b.z), 2) <= deltaVariance; - } - - protected bool Approximately(Quaternion a, Quaternion b) - { - var deltaVariance = m_DeltaVarQauternion; - return Mathf.Abs(a.x - b.x) <= deltaVariance && - Mathf.Abs(a.y - b.y) <= deltaVariance && - Mathf.Abs(a.z - b.z) <= deltaVariance && - Mathf.Abs(a.w - b.w) <= deltaVariance; - } - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs.meta b/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs.meta deleted file mode 100644 index b48a2d0..0000000 --- a/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4a759aeb53d12d842899381b411f3d2e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs b/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs deleted file mode 100644 index 397d4f0..0000000 --- a/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs +++ /dev/null @@ -1,749 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.Transports.UTP; -#if UTP_TRANSPORT_2_0_ABOVE -using Unity.Networking.Transport; -#endif -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class DistributedAuthorityCodecTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - // Use the CMB Service for all tests - protected override bool UseCMBService() => true; - - // Set the network topology to distributed authority for all tests - protected override NetworkTopologyTypes OnGetNetworkTopologyType() => NetworkTopologyTypes.DistributedAuthority; - - private CodecTestHooks m_ClientCodecHook; - private NetworkManager Client => m_ClientNetworkManagers[0]; - - private string m_TransportHost = Environment.GetEnvironmentVariable("NGO_HOST") ?? "127.0.0.1"; - private const int k_TransportPort = 7777; - private const int k_ClientId = 0; - - private GameObject m_SpawnObject; - - internal class TestNetworkComponent : NetworkBehaviour - { - public NetworkList MyNetworkList = new NetworkList(new List { 1, 2, 3 }); - public NetworkVariable MyNetworkVar = new NetworkVariable(3); - - [Rpc(SendTo.Authority)] - public void TestAuthorityRpc(byte[] _) - { - } - } - - protected override void OnOneTimeSetup() - { - // Prevents the tests from running if no CMB Service is detected -#if !UTP_TRANSPORT_2_0_ABOVE - Assert.Ignore("ignoring DA codec tests because UTP transport must be 2.0"); -#else - if (!CanConnectToServer(m_TransportHost, k_TransportPort)) - { - Assert.Ignore("ignoring DA codec tests because UTP transport cannot connect to the runtime"); - } -#endif - base.OnOneTimeSetup(); - } - - /// - /// Add any additional components to default player prefab - /// - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - base.OnCreatePlayerPrefab(); - } - - /// - /// Modify NetworkManager instances for settings specific to tests - /// - protected override void OnServerAndClientsCreated() - { - var utpTransport = Client.gameObject.AddComponent(); - Client.NetworkConfig.NetworkTransport = utpTransport; - Client.NetworkConfig.EnableSceneManagement = false; - Client.NetworkConfig.AutoSpawnPlayerPrefabClientSide = true; - utpTransport.ConnectionData.Address = Dns.GetHostAddresses(m_TransportHost).First().ToString(); - utpTransport.ConnectionData.Port = k_TransportPort; - Client.LogLevel = LogLevel.Developer; - - // Validate we are in distributed authority mode with client side spawning and using CMB Service - Assert.True(Client.NetworkConfig.NetworkTopology == NetworkTopologyTypes.DistributedAuthority, "Distributed authority topology is not set!"); - Assert.True(Client.AutoSpawnPlayerPrefabClientSide, "Client side spawning is not set!"); - Assert.True(Client.CMBServiceConnection, "CMBServiceConnection is not set!"); - - // Create a prefab for creating and destroying tests (auto-registers with NetworkManagers) - m_SpawnObject = CreateNetworkObjectPrefab("TestObject"); - m_SpawnObject.AddComponent(); - - // Ignore the client connection timeout after starting the client - m_BypassConnectionTimeout = true; - } - - protected override IEnumerator OnStartedServerAndClients() - { - // Validate the NetworkManager are in distributed authority mode - Assert.True(Client.DistributedAuthorityMode, "Distributed authority is not set!"); - - // Register hooks after starting clients and server (in this case just the one client) - // We do this at this point in time because the MessageManager exists (happens within the same call stack when starting NetworkManagers) - m_ClientCodecHook = new CodecTestHooks(); - Client.MessageManager.Hook(m_ClientCodecHook); - yield return base.OnStartedServerAndClients(); - - // wait for client to connect since m_BypassConnectionTimeout - yield return WaitForConditionOrTimeOut(() => Client.LocalClient.PlayerObject != null); - AssertOnTimeout($"Timed out waiting for the client's player to be spanwed!"); - } - - [UnityTest] - public IEnumerator AuthorityRpc() - { - var player = Client.LocalClient.PlayerObject; - player.OwnerClientId = Client.LocalClientId + 1; - - var networkComponent = player.GetComponent(); - networkComponent.UpdateNetworkProperties(); - networkComponent.TestAuthorityRpc(new byte[] { 1, 2, 3, 4 }); - - // Universal Rpcs are sent as a ProxyMessage (which contains an RpcMessage) - yield return m_ClientCodecHook.WaitForMessageReceived(); - } - - [UnityTest] - public IEnumerator ChangeOwnership() - { - var message = new ChangeOwnershipMessage - { - DistributedAuthorityMode = true, - NetworkObjectId = 100, - OwnerClientId = 2, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator ClientConnected() - { - var message = new ClientConnectedMessage() - { - ClientId = 2, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator ClientDisconnected() - { - var message = new ClientDisconnectedMessage() - { - ClientId = 2, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator CreateObject() - { - SpawnObject(m_SpawnObject, Client); - yield return m_ClientCodecHook.WaitForMessageReceived(); - } - - [UnityTest] - public IEnumerator DestroyObject() - { - var spawnedObject = SpawnObject(m_SpawnObject, Client); - yield return m_ClientCodecHook.WaitForMessageReceived(); - spawnedObject.GetComponent().Despawn(); - yield return m_ClientCodecHook.WaitForMessageReceived(); - } - - [UnityTest] - public IEnumerator Disconnect() - { - var message = new DisconnectReasonMessage - { - Reason = "test" - }; - - return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator NamedMessage() - { - var writeBuffer = new FastBufferWriter(sizeof(int), Allocator.Temp); - writeBuffer.WriteValueSafe(5); - - var message = new NamedMessage - { - Hash = 3, - SendData = writeBuffer, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator NetworkVariableDelta() - { - var message = new NetworkVariableDeltaMessage - { - NetworkObjectId = 0, - NetworkBehaviourIndex = 1, - DeliveryMappedNetworkVariableIndex = new HashSet { 2, 3, 4 }, - TargetClientId = 5, - NetworkBehaviour = Client.LocalClient.PlayerObject.GetComponent(), - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator NetworkVariableDelta_WithValueUpdate() - { - var networkObj = CreateNetworkObjectPrefab("TestObject"); - networkObj.AddComponent(); - var instance = SpawnObject(networkObj, Client); - yield return m_ClientCodecHook.WaitForMessageReceived(); - var component = instance.GetComponent(); - - var newValue = 5; - component.MyNetworkVar.Value = newValue; - yield return m_ClientCodecHook.WaitForMessageReceived(); - Assert.AreEqual(newValue, component.MyNetworkVar.Value); - } - - [UnityTest] - public IEnumerator NetworkListDelta_WithValueUpdate() - { - var networkObj = CreateNetworkObjectPrefab("TestObject"); - networkObj.AddComponent(); - var instance = SpawnObject(networkObj, Client); - yield return m_ClientCodecHook.WaitForMessageReceived(); - var component = instance.GetComponent(); - - component.MyNetworkList.Add(5); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.Add(6); - component.MyNetworkList.Add(7); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.Insert(1, 8); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.Insert(8, 11); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.Remove(6); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.RemoveAt(2); - yield return m_ClientCodecHook.WaitForMessageReceived(); - component.MyNetworkList.Clear(); - yield return m_ClientCodecHook.WaitForMessageReceived(); - } - - [UnityTest] - public IEnumerator ParentSync() - { - var message = new ParentSyncMessage - { - NetworkObjectId = 0, - WorldPositionStays = true, - IsLatestParentSet = false, - Position = new Vector3(1, 2, 3), - Rotation = new Quaternion(4, 5, 6, 7), - Scale = new Vector3(8, 9, 10), - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SessionOwner() - { - var message = new SessionOwnerMessage() - { - SessionOwner = 2, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator ServerLog() - { - var message = new ServerLogMessage() - { - LogType = NetworkLog.LogType.Info, - Message = "test", - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator UnnamedMessage() - { - var writeBuffer = new FastBufferWriter(sizeof(int), Allocator.Temp); - writeBuffer.WriteValueSafe(5); - - var message = new UnnamedMessage - { - SendData = writeBuffer, - }; - - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageLoad() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.Load, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageLoadWithObjects() - { - Client.SceneManager.SkipSceneHandling = true; - var prefabNetworkObject = m_SpawnObject.GetComponent(); - - Client.SceneManager.ScenePlacedObjects.Add(0, new Dictionary() - { - { 1, prefabNetworkObject } - }); - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.Load, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageUnload() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.Unload, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageLoadComplete() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.LoadComplete, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageUnloadComplete() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.UnloadComplete, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageLoadCompleted() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.LoadEventCompleted, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - ClientsCompleted = new List() { k_ClientId }, - ClientsTimedOut = new List() { 123456789 }, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageUnloadLoadCompleted() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.UnloadEventCompleted, - LoadSceneMode = LoadSceneMode.Single, - SceneEventProgressId = Guid.NewGuid(), - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - ClientsCompleted = new List() { k_ClientId }, - ClientsTimedOut = new List() { 123456789 }, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageSynchronize() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.Synchronize, - LoadSceneMode = LoadSceneMode.Single, - ClientSynchronizationMode = LoadSceneMode.Single, - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - ScenesToSynchronize = new Queue() - }; - eventData.ScenesToSynchronize.Enqueue(101); - eventData.SceneHandlesToSynchronize = new Queue(); - eventData.SceneHandlesToSynchronize.Enqueue(202); - - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageReSynchronize() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.ReSynchronize, - LoadSceneMode = LoadSceneMode.Single, - ClientSynchronizationMode = LoadSceneMode.Single, - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageSynchronizeComplete() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.ReSynchronize, - LoadSceneMode = LoadSceneMode.Single, - ClientSynchronizationMode = LoadSceneMode.Single, - SceneHash = XXHash.Hash32("SomeRandomSceneName"), - SceneHandle = 23456, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest] - public IEnumerator SceneEventMessageActiveSceneChanged() - { - Client.SceneManager.SkipSceneHandling = true; - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.ActiveSceneChanged, - ActiveSceneHash = XXHash.Hash32("ActiveScene") - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - [UnityTest, Ignore("Serializing twice causes data to disappear in the SceneManager for this event")] - public IEnumerator SceneEventMessageObjectSceneChanged() - { - Client.SceneManager.SkipSceneHandling = true; - var prefabNetworkObject = m_SpawnObject.GetComponent(); - Client.SceneManager.ObjectsMigratedIntoNewScene = new Dictionary>> - { - { 0, new Dictionary>()} - }; - - Client.SceneManager.ObjectsMigratedIntoNewScene[0].Add(Client.LocalClientId, new List() { prefabNetworkObject }); - var eventData = new SceneEventData(Client) - { - SceneEventType = SceneEventType.ObjectSceneChanged, - }; - - var message = new SceneEventMessage() - { - EventData = eventData - }; - yield return SendMessage(ref message); - } - - - private IEnumerator SendMessage(ref T message) where T : INetworkMessage - { - Client.MessageManager.SetVersion(k_ClientId, XXHash.Hash32(typeof(T).FullName), 0); - - var clientIds = new NativeArray(1, Allocator.Temp); - clientIds[0] = k_ClientId; - Client.MessageManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientIds); - Client.MessageManager.ProcessSendQueues(); - return m_ClientCodecHook.WaitForMessageReceived(message); - } - -#if UTP_TRANSPORT_2_0_ABOVE - private static bool CanConnectToServer(string host, ushort port, double timeoutMs = 100) - { - var address = Dns.GetHostAddresses(host).First(); - var endpoint = NetworkEndpoint.Parse(address.ToString(), port); - - var driver = NetworkDriver.Create(); - var connection = driver.Connect(endpoint); - - var start = DateTime.Now; - var ev = Networking.Transport.NetworkEvent.Type.Empty; - while (ev != Networking.Transport.NetworkEvent.Type.Connect) - { - driver.ScheduleUpdate().Complete(); - ev = driver.PopEventForConnection(connection, out _, out _); - - if (DateTime.Now - start > TimeSpan.FromMilliseconds(timeoutMs)) - { - return false; - } - } - - driver.Disconnect(connection); - return true; - } -#endif - } - - internal class CodecTestHooks : INetworkHooks - { - private Dictionary> m_ExpectedMessages = new Dictionary>(); - private Dictionary> m_ReceivedMessages = new Dictionary>(); - - private struct TestMessage - { - public string Name; - public byte[] Data; - } - - public void OnBeforeSendMessage(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage - { - if (message is ConnectionRequestMessage) - { - return; - } - - var writer = new FastBufferWriter(1024, Allocator.Temp); - message.Serialize(writer, 0); - - var testName = TestContext.CurrentContext.Test.Name; - if (!m_ExpectedMessages.ContainsKey(testName)) - { - m_ExpectedMessages[testName] = new Queue(); - } - - m_ExpectedMessages[testName].Enqueue(new TestMessage - { - Name = typeof(T).ToString(), - Data = writer.ToArray(), - }); - - writer.Dispose(); - } - - public void OnAfterSendMessage(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage - { - } - - public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - - public void OnAfterReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - - public void OnBeforeSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - - public void OnAfterSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - - public void OnBeforeReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - - public void OnAfterReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - - public bool OnVerifyCanSend(ulong destinationId, Type messageType, NetworkDelivery delivery) - { - return true; - } - - public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReader messageContent, ref NetworkContext context) - { - if (messageType == typeof(ConnectionApprovedMessage)) - { - return true; - } - - var testName = TestContext.CurrentContext.Test.Name; - Assert.True(m_ExpectedMessages.ContainsKey(testName)); - Assert.IsNotEmpty(m_ExpectedMessages[testName]); - - var nextMessage = m_ExpectedMessages[testName].Dequeue(); - Assert.AreEqual(messageType.ToString(), nextMessage.Name, $"received unexpected message type: {messageType}"); - - if (!m_ReceivedMessages.ContainsKey(testName)) - { - m_ReceivedMessages[testName] = new HashSet(); - } - - m_ReceivedMessages[testName].Add(messageType.ToString()); - - // ServerLogMessage is an exception - it gets decoded correctly, but the bytes from the runtime do not directly match those sent by the SDK. - if (messageType == typeof(ServerLogMessage)) - { - return true; - } - - var expectedBytes = nextMessage.Data; - var receivedBytes = messageContent.ToArray(); - Assert.AreEqual(expectedBytes, receivedBytes); - - return true; - } - - public void OnBeforeHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - - public void OnAfterHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - - public IEnumerator WaitForMessageReceived(float timeout = 5) where T : INetworkMessage - { - var testName = TestContext.CurrentContext.Test.Name; - var messageType = typeof(T).FullName; - var startTime = Time.realtimeSinceStartup; - - while ((!m_ReceivedMessages.ContainsKey(testName) || !m_ReceivedMessages[testName].Contains(messageType)) && Time.realtimeSinceStartup - startTime < timeout) - { - yield return null; - } - - Assert.True(m_ReceivedMessages.ContainsKey(testName), "failed to receive any messages"); - Assert.True(m_ReceivedMessages[testName].Contains(messageType), $"failed to receive {messageType} message, received: {string.Join(", ", m_ReceivedMessages[testName])}"); - - // Reset received messages - m_ReceivedMessages[testName] = new HashSet(); - } - - public IEnumerator WaitForMessageReceived(T _, float timeout = 5) where T : INetworkMessage - { - return WaitForMessageReceived(timeout: timeout); - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs.meta b/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs.meta deleted file mode 100644 index 72b937f..0000000 --- a/Tests/Runtime/DistributedAuthority/DistributedAuthorityCodecTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4cec6e6e1b9bdb746806290355d8cb50 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs b/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs deleted file mode 100644 index 1ebb0f0..0000000 --- a/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost, true)] - [TestFixture(HostOrServer.DAHost, false)] - public class ExtendedNetworkShowAndHideTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 3; - private bool m_EnableSceneManagement; - private GameObject m_ObjectToSpawn; - private NetworkObject m_SpawnedObject; - private NetworkManager m_ClientToHideFrom; - private NetworkManager m_LateJoinClient; - private NetworkManager m_SpawnOwner; - - public ExtendedNetworkShowAndHideTests(HostOrServer hostOrServer, bool enableSceneManagement) : base(hostOrServer) - { - m_EnableSceneManagement = enableSceneManagement; - } - - protected override void OnServerAndClientsCreated() - { - if (!UseCMBService()) - { - m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; - } - - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; - } - - m_ObjectToSpawn = CreateNetworkObjectPrefab("TestObject"); - m_ObjectToSpawn.SetActive(false); - - base.OnServerAndClientsCreated(); - } - - private bool AllClientsSpawnedObject() - { - if (!UseCMBService()) - { - if (!s_GlobalNetworkObjects.ContainsKey(m_ServerNetworkManager.LocalClientId)) - { - return false; - } - if (!s_GlobalNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_SpawnedObject.NetworkObjectId)) - { - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!s_GlobalNetworkObjects.ContainsKey(client.LocalClientId)) - { - return false; - } - if (!s_GlobalNetworkObjects[client.LocalClientId].ContainsKey(m_SpawnedObject.NetworkObjectId)) - { - return false; - } - } - return true; - } - - private bool IsClientPromotedToSessionOwner() - { - if (!UseCMBService()) - { - if (m_ServerNetworkManager.CurrentSessionOwner != m_ClientToHideFrom.LocalClientId) - { - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!client.IsConnectedClient) - { - continue; - } - if (client.CurrentSessionOwner != m_ClientToHideFrom.LocalClientId) - { - return false; - } - } - return true; - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - m_LateJoinClient = networkManager; - networkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; - networkManager.NetworkConfig.Prefabs = m_SpawnOwner.NetworkConfig.Prefabs; - base.OnNewClientCreated(networkManager); - } - - /// - /// This test validates the following NetworkShow - NetworkHide issue: - /// - During a session, a spawned object is hidden from a client. - /// - The current session owner disconnects and the client the object is hidden from is prommoted to the session owner. - /// - A new client joins and the newly promoted session owner synchronizes the newly joined client with only objects visible to it. - /// - Any already connected non-session owner client should "NetworkShow" the object to the newly connected client - /// (but only if the hidden object has SpawnWithObservers enabled) - /// - [UnityTest] - public IEnumerator HiddenObjectPromotedSessionOwnerNewClientSynchronizes() - { - // Get the test relative session owner - var sessionOwner = UseCMBService() ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - m_SpawnOwner = UseCMBService() ? m_ClientNetworkManagers[1] : m_ClientNetworkManagers[0]; - m_ClientToHideFrom = UseCMBService() ? m_ClientNetworkManagers[NumberOfClients - 1] : m_ClientNetworkManagers[1]; - m_ObjectToSpawn.SetActive(true); - - // Spawn the object with a non-session owner client - m_SpawnedObject = SpawnObject(m_ObjectToSpawn, m_SpawnOwner).GetComponent(); - yield return WaitForConditionOrTimeOut(AllClientsSpawnedObject); - AssertOnTimeout($"Not all clients spawned and instance of {m_SpawnedObject.name}"); - - // Hide the spawned object from the to be promoted session owner - m_SpawnedObject.NetworkHide(m_ClientToHideFrom.LocalClientId); - - yield return WaitForConditionOrTimeOut(() => !m_ClientToHideFrom.SpawnManager.SpawnedObjects.ContainsKey(m_SpawnedObject.NetworkObjectId)); - AssertOnTimeout($"{m_SpawnedObject.name} was not hidden from Client-{m_ClientToHideFrom.LocalClientId}!"); - - // Promoted a new session owner (DAHost promotes while CMB Session we disconnect the current session owner) - if (!UseCMBService()) - { - m_ServerNetworkManager.PromoteSessionOwner(m_ClientToHideFrom.LocalClientId); - } - else - { - sessionOwner.Shutdown(); - } - - // Wait for the new session owner to be promoted and for all clients to acknowledge the promotion - yield return WaitForConditionOrTimeOut(IsClientPromotedToSessionOwner); - AssertOnTimeout($"Client-{m_ClientToHideFrom.LocalClientId} was not promoted as session owner on all client instances!"); - - // Connect a new client instance - yield return CreateAndStartNewClient(); - - // Assure the newly connected client is synchronized with the NetworkObject hidden from the newly promoted session owner - yield return WaitForConditionOrTimeOut(() => m_LateJoinClient.SpawnManager.SpawnedObjects.ContainsKey(m_SpawnedObject.NetworkObjectId)); - AssertOnTimeout($"Client-{m_LateJoinClient.LocalClientId} never spawned {nameof(NetworkObject)} {m_SpawnedObject.name}!"); - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs.meta b/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs.meta deleted file mode 100644 index 5d22751..0000000 --- a/Tests/Runtime/DistributedAuthority/ExtendedNetworkShowAndHideTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: a6389d04d9080b24b99de7e6900a064c \ No newline at end of file diff --git a/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs b/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs deleted file mode 100644 index d7890c2..0000000 --- a/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs +++ /dev/null @@ -1,298 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - [TestFixture(HostOrServer.DAHost)] - internal class NetworkClientAndPlayerObjectTests : NetcodeIntegrationTest - { - private const int k_PlayerPrefabCount = 6; - protected override int NumberOfClients => 2; - - private List m_PlayerPrefabs = new List(); - private Dictionary m_ChangedPlayerPrefabs = new Dictionary(); - - - public NetworkClientAndPlayerObjectTests(HostOrServer hostOrServer) : base(hostOrServer) - { - } - - protected override IEnumerator OnTearDown() - { - m_PlayerPrefabs.Clear(); - return base.OnTearDown(); - } - - protected override void OnServerAndClientsCreated() - { - m_PlayerPrefabs.Clear(); - for (int i = 0; i < k_PlayerPrefabCount; i++) - { - m_PlayerPrefabs.Add(CreateNetworkObjectPrefab($"PlayerPrefab{i}")); - } - base.OnServerAndClientsCreated(); - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs; - if (m_DistributedAuthority) - { - networkManager.OnFetchLocalPlayerPrefabToSpawn = FetchPlayerPrefabToSpawn; - } - base.OnNewClientCreated(networkManager); - } - - /// - /// Only for distributed authority mode - /// - /// a unique player prefab for the player - private GameObject FetchPlayerPrefabToSpawn() - { - var prefabObject = GetRandomPlayerPrefab(); - var clientId = m_ClientNetworkManagers[m_ClientNetworkManagers.Length - 1].LocalClientId; - m_ChangedPlayerPrefabs.Add(clientId, prefabObject.GlobalObjectIdHash); - return prefabObject.gameObject; - } - - - private StringBuilder m_ErrorLogLevel3 = new StringBuilder(); - private StringBuilder m_ErrorLogLevel2 = new StringBuilder(); - private StringBuilder m_ErrorLogLevel1 = new StringBuilder(); - - private bool ValidateNetworkClient(NetworkClient networkClient) - { - m_ErrorLogLevel3.Clear(); - var success = true; - if (networkClient == null) - { - m_ErrorLogLevel3.Append($"[NetworkClient is NULL]"); - // Log error - success = false; - } - if (!networkClient.IsConnected) - { - m_ErrorLogLevel3.Append($"[NetworkClient {nameof(NetworkClient.IsConnected)}] is false]"); - // Log error - success = false; - } - if (networkClient.PlayerObject == null) - { - m_ErrorLogLevel3.Append($"[NetworkClient {nameof(NetworkClient.PlayerObject)}] is NULL]"); - // Log error - success = false; - } - return success; - } - - private bool ValidateNetworkManagerNetworkClients(NetworkManager networkManager) - { - var success = true; - m_ErrorLogLevel2.Clear(); - - // Number of connected clients plus the DAHost - var expectedCount = m_ClientNetworkManagers.Length + (m_UseHost ? 1 : 0); - - if (networkManager.ConnectedClients.Count != expectedCount) - { - m_ErrorLogLevel2.Append($"[{nameof(NetworkManager.ConnectedClients)} count: {networkManager.ConnectedClients.Count} vs expected count: {expectedCount}]"); - // Log error - success = false; - } - - if (m_UseHost && !ValidateNetworkClient(networkManager.LocalClient)) - { - m_ErrorLogLevel2.Append($"[Local NetworkClient: --({m_ErrorLogLevel3})--]"); - // Log error - success = false; - } - - foreach (var networkClient in networkManager.ConnectedClients) - { - // When just running a server, ignore the server's local NetworkClient - if (!m_UseHost && networkManager.IsServer) - { - continue; - } - if (!ValidateNetworkClient(networkManager.LocalClient)) - { - // Log error - success = false; - m_ErrorLogLevel2.Append($"[NetworkClient-{networkManager.LocalClientId}: --({m_ErrorLogLevel3})--]"); - } - } - return success; - } - - private bool AllNetworkClientsValidated() - { - m_ErrorLogLevel1.Clear(); - var success = true; - - if (!UseCMBService()) - { - if (!ValidateNetworkManagerNetworkClients(m_ServerNetworkManager)) - { - m_ErrorLogLevel1.AppendLine($"[Client-{m_ServerNetworkManager.LocalClientId}]{m_ErrorLogLevel2}"); - // Log error - success = false; - } - } - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (!ValidateNetworkManagerNetworkClients(clientNetworkManager)) - { - m_ErrorLogLevel1.AppendLine($"[Client-{clientNetworkManager.LocalClientId}]{m_ErrorLogLevel2}"); - // Log error - success = false; - } - } - return success; - } - - /// - /// Validates that all NetworkManager instances have valid NetworkClients for all connected clients - /// Validates the same thing when a client late joins and when a client disconnects. - /// - [UnityTest] - public IEnumerator ValidateNetworkClients() - { - // Validate the initial clients created - yield return WaitForConditionOrTimeOut(AllNetworkClientsValidated); - AssertOnTimeout($"[Start] Not all NetworkClients were valid!\n{m_ErrorLogLevel1}"); - - // Late join a player and revalidate all instances - yield return CreateAndStartNewClient(); - yield return WaitForConditionOrTimeOut(AllNetworkClientsValidated); - AssertOnTimeout($"[Late Join] Not all NetworkClients were valid!\n{m_ErrorLogLevel1}"); - - // Disconnect a player and revalidate all instances - var initialCount = m_ClientNetworkManagers.Length; - yield return StopOneClient(m_ClientNetworkManagers[m_ClientNetworkManagers.Length - 1], true); - // Sanity check to assure we removed the NetworkManager from m_ClientNetworkManagers - Assert.False(initialCount == m_ClientNetworkManagers.Length, $"Disconnected player and expected total number of client {nameof(NetworkManager)}s " + - $"to be {initialCount - 1} but it was still {initialCount}!"); - - yield return WaitForConditionOrTimeOut(AllNetworkClientsValidated); - AssertOnTimeout($"[Client Disconnect] Not all NetworkClients were valid!\n{m_ErrorLogLevel1}"); - - } - - /// - /// Verify that all NetworkClients are pointing to the correct player object, even if - /// the player object is changed. - /// - private bool ValidatePlayerObjectOnClients(NetworkManager clientToValidate) - { - m_ErrorLogLevel2.Clear(); - var success = true; - var expectedGlobalObjectIdHash = m_ChangedPlayerPrefabs[clientToValidate.LocalClientId]; - if (expectedGlobalObjectIdHash != clientToValidate.LocalClient.PlayerObject.GlobalObjectIdHash) - { - m_ErrorLogLevel2.Append($"[Local Prefab Mismatch][Expected GlobalObjectIdHash: {expectedGlobalObjectIdHash} but was {clientToValidate.LocalClient.PlayerObject.GlobalObjectIdHash}]"); - success = false; - } - - foreach (var client in m_ClientNetworkManagers) - { - if (client == clientToValidate) - { - continue; - } - var remoteNetworkClient = client.ConnectedClients[clientToValidate.LocalClientId]; - if (expectedGlobalObjectIdHash != remoteNetworkClient.PlayerObject.GlobalObjectIdHash) - { - m_ErrorLogLevel2.Append($"[Client-{client.LocalClientId} Prefab Mismatch][Expected GlobalObjectIdHash: {expectedGlobalObjectIdHash} but was {remoteNetworkClient.PlayerObject.GlobalObjectIdHash}]"); - success = false; - } - } - return success; - } - - private bool ValidateAllPlayerObjects() - { - m_ErrorLogLevel1.Clear(); - var success = true; - if (m_UseHost && !UseCMBService()) - { - if (!ValidatePlayerObjectOnClients(m_ServerNetworkManager)) - { - m_ErrorLogLevel1.AppendLine($"[Client-{m_ServerNetworkManager.LocalClientId}]{m_ErrorLogLevel2}"); - success = false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!ValidatePlayerObjectOnClients(client)) - { - m_ErrorLogLevel1.AppendLine($"[Client-{client.LocalClientId}]{m_ErrorLogLevel2}"); - success = false; - } - } - - return success; - } - - private NetworkObject GetRandomPlayerPrefab() - { - return m_PlayerPrefabs[Random.Range(0, m_PlayerPrefabs.Count() - 1)].GetComponent(); - } - - /// - /// Validates that when a client changes their player object that all connected client instances mirror the - /// client's new player object. - /// - [UnityTest] - public IEnumerator ValidatePlayerObjects() - { - // Just do a quick validation for all connected client's NetworkClients - yield return WaitForConditionOrTimeOut(AllNetworkClientsValidated); - AssertOnTimeout($"Not all NetworkClients were valid!\n{m_ErrorLogLevel1}"); - - // Now, have each client spawn a new player object - m_ChangedPlayerPrefabs.Clear(); - var playerInstance = (GameObject)null; - var playerPrefabToSpawn = (NetworkObject)null; - if (m_UseHost) - { - playerPrefabToSpawn = GetRandomPlayerPrefab(); - playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, m_ServerNetworkManager); - m_ChangedPlayerPrefabs.Add(m_ServerNetworkManager.LocalClientId, playerPrefabToSpawn.GlobalObjectIdHash); - } - - foreach (var client in m_ClientNetworkManagers) - { - playerPrefabToSpawn = GetRandomPlayerPrefab(); - playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, client); - m_ChangedPlayerPrefabs.Add(client.LocalClientId, playerPrefabToSpawn.GlobalObjectIdHash); - } - - // Validate that all connected clients' NetworkClient instances have the correct player object for each connected client - yield return WaitForConditionOrTimeOut(ValidateAllPlayerObjects); - AssertOnTimeout($"[Existing Clients] Not all NetworkClient player objects were valid!\n{m_ErrorLogLevel1}"); - - // Distributed authority only feature validation (NetworkManager.OnFetchLocalPlayerPrefabToSpawn) - if (m_DistributedAuthority) - { - // Now test the fetch prefab callback to assure that this is working correctly. - // Start a new client and wait for it to connect - yield return CreateAndStartNewClient(); - // Do another validation pass. - yield return WaitForConditionOrTimeOut(ValidateAllPlayerObjects); - AssertOnTimeout($"[Late Joined Client] Not all NetworkClient player objects were valid!\n{m_ErrorLogLevel1}"); - } - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs.meta b/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs.meta deleted file mode 100644 index bacb517..0000000 --- a/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: db4c955c05fdc194eb47e7774b9c5101 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs b/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs deleted file mode 100644 index beccbdd..0000000 --- a/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs +++ /dev/null @@ -1,406 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class OwnershipPermissionsTests : IntegrationTestWithApproximation - { - private GameObject m_PermissionsObject; - - private StringBuilder m_ErrorLog = new StringBuilder(); - - protected override int NumberOfClients => 4; - - public OwnershipPermissionsTests() : base(HostOrServer.DAHost) - { - } - - protected override IEnumerator OnSetup() - { - m_ObjectToValidate = null; - OwnershipPermissionsTestHelper.CurrentOwnedInstance = null; - return base.OnSetup(); - } - - protected override void OnServerAndClientsCreated() - { - m_PermissionsObject = CreateNetworkObjectPrefab("PermObject"); - m_PermissionsObject.AddComponent(); - - base.OnServerAndClientsCreated(); - } - - private NetworkObject m_ObjectToValidate; - - private bool ValidateObjectSpawnedOnAllClients() - { - m_ErrorLog.Clear(); - - var networkObjectId = m_ObjectToValidate.NetworkObjectId; - var name = m_ObjectToValidate.name; - if (!UseCMBService() && !m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) - { - m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} has not spawned {name}!"); - return false; - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!client.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) - { - m_ErrorLog.Append($"Client-{client.LocalClientId} has not spawned {name}!"); - return false; - } - } - return true; - } - - private bool ValidatePermissionsOnAllClients() - { - var currentPermissions = (ushort)m_ObjectToValidate.Ownership; - var otherPermissions = (ushort)0; - var networkObjectId = m_ObjectToValidate.NetworkObjectId; - var objectName = m_ObjectToValidate.name; - m_ErrorLog.Clear(); - if (!UseCMBService()) - { - otherPermissions = (ushort)m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId].Ownership; - if (currentPermissions != otherPermissions) - { - m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} permissions for {objectName} is {otherPermissions} when it should be {currentPermissions}!"); - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - otherPermissions = (ushort)client.SpawnManager.SpawnedObjects[networkObjectId].Ownership; - if (currentPermissions != otherPermissions) - { - m_ErrorLog.Append($"Client-{client.LocalClientId} permissions for {objectName} is {otherPermissions} when it should be {currentPermissions}!"); - return false; - } - } - return true; - } - - private bool ValidateAllInstancesAreOwnedByClient(ulong clientId) - { - var networkObjectId = m_ObjectToValidate.NetworkObjectId; - var otherNetworkObject = (NetworkObject)null; - m_ErrorLog.Clear(); - if (!UseCMBService()) - { - otherNetworkObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId]; - if (otherNetworkObject.OwnerClientId != clientId) - { - m_ErrorLog.Append($"[Client-{m_ServerNetworkManager.LocalClientId}][{otherNetworkObject.name}] Expected owner to be {clientId} but it was {otherNetworkObject.OwnerClientId}!"); - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - otherNetworkObject = client.SpawnManager.SpawnedObjects[networkObjectId]; - if (otherNetworkObject.OwnerClientId != clientId) - { - m_ErrorLog.Append($"[Client-{client.LocalClientId}][{otherNetworkObject.name}] Expected owner to be {clientId} but it was {otherNetworkObject.OwnerClientId}!"); - return false; - } - } - return true; - } - - [UnityTest] - public IEnumerator ValidateOwnershipPermissionsTest() - { - var firstInstance = SpawnObject(m_PermissionsObject, m_ClientNetworkManagers[0]).GetComponent(); - OwnershipPermissionsTestHelper.CurrentOwnedInstance = firstInstance; - var firstInstanceHelper = firstInstance.GetComponent(); - var networkObjectId = firstInstance.NetworkObjectId; - m_ObjectToValidate = OwnershipPermissionsTestHelper.CurrentOwnedInstance; - yield return WaitForConditionOrTimeOut(ValidateObjectSpawnedOnAllClients); - AssertOnTimeout($"[Failed To Spawn] {firstInstance.name}: \n {m_ErrorLog}"); - - // Validate the base non-assigned persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - ////////////////////////////////////// - // Setting & Removing Ownership Flags: - ////////////////////////////////////// - - // Now, cycle through all permissions and validate that when the owner changes them the change - // is synchronized on all non-owner clients. - foreach (var permissionObject in Enum.GetValues(typeof(NetworkObject.OwnershipStatus))) - { - var permission = (NetworkObject.OwnershipStatus)permissionObject; - // Add the status - firstInstance.SetOwnershipStatus(permission); - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Add][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - // Remove the status unless it is None (ignore None). - if (permission == NetworkObject.OwnershipStatus.None) - { - continue; - } - firstInstance.RemoveOwnershipStatus(permission); - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Remove][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - } - - //Add multiple flags at the same time - var multipleFlags = NetworkObject.OwnershipStatus.Transferable | NetworkObject.OwnershipStatus.Distributable | NetworkObject.OwnershipStatus.RequestRequired; - firstInstance.SetOwnershipStatus(multipleFlags, true); - Assert.IsTrue(firstInstance.HasOwnershipStatus(multipleFlags), $"[Set][Multi-flag Failure] Expected: {(ushort)multipleFlags} but was {(ushort)firstInstance.Ownership}!"); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Set Multiple][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - // Remove multiple flags at the same time - multipleFlags = NetworkObject.OwnershipStatus.Transferable | NetworkObject.OwnershipStatus.RequestRequired; - firstInstance.RemoveOwnershipStatus(multipleFlags); - // Validate the two flags no longer are set - Assert.IsFalse(firstInstance.HasOwnershipStatus(multipleFlags), $"[Remove][Multi-flag Failure] Expected: {(ushort)NetworkObject.OwnershipStatus.Distributable} but was {(ushort)firstInstance.Ownership}!"); - // Validate that the Distributable flag is still set - Assert.IsTrue(firstInstance.HasOwnershipStatus(NetworkObject.OwnershipStatus.Distributable), $"[Remove][Multi-flag Failure] Expected: {(ushort)NetworkObject.OwnershipStatus.Distributable} but was {(ushort)firstInstance.Ownership}!"); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Set Multiple][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - ////////////////////// - // Changing Ownership: - ////////////////////// - - // Clear the flags, set the permissions to transferrable, and lock ownership in one pass. - firstInstance.SetOwnershipStatus(NetworkObject.OwnershipStatus.Transferable, true, NetworkObject.OwnershipLockActions.SetAndLock); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Reset][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - var secondInstance = m_ClientNetworkManagers[1].SpawnManager.SpawnedObjects[networkObjectId]; - var secondInstanceHelper = secondInstance.GetComponent(); - - secondInstance.ChangeOwnership(m_ClientNetworkManagers[1].LocalClientId); - Assert.IsTrue(secondInstanceHelper.OwnershipPermissionsFailureStatus == NetworkObject.OwnershipPermissionsFailureStatus.Locked, - $"Expected {secondInstance.name} to return {NetworkObject.OwnershipPermissionsFailureStatus.Locked} but its permission failure" + - $" status is {secondInstanceHelper.OwnershipPermissionsFailureStatus}!"); - - firstInstance.SetOwnershipLock(false); - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Unlock][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - // Sanity check to assure this client's instance isn't already the owner. - Assert.True(!secondInstance.IsOwner, $"[Ownership Check] Client-{m_ClientNetworkManagers[1].LocalClientId} already is the owner!"); - // Now try to acquire ownership - secondInstance.ChangeOwnership(m_ClientNetworkManagers[1].LocalClientId); - - // Validate the persmissions value for all instances are the same - yield return WaitForConditionOrTimeOut(() => secondInstance.IsOwner); - AssertOnTimeout($"[Acquire Ownership Failed] Client-{m_ClientNetworkManagers[1].LocalClientId} failed to get ownership!"); - - m_ObjectToValidate = OwnershipPermissionsTestHelper.CurrentOwnedInstance; - // Validate all other client instances are showing the same owner - yield return WaitForConditionOrTimeOut(() => ValidateAllInstancesAreOwnedByClient(m_ClientNetworkManagers[1].LocalClientId)); - AssertOnTimeout($"[Ownership Mismatch] {secondInstance.name}: \n {m_ErrorLog}"); - - // Clear the flags, set the permissions to RequestRequired, and lock ownership in one pass. - secondInstance.SetOwnershipStatus(NetworkObject.OwnershipStatus.RequestRequired, true); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Unlock][Permissions Mismatch] {secondInstance.name}: \n {m_ErrorLog}"); - - // Attempt to acquire ownership by just changing it - firstInstance.ChangeOwnership(firstInstance.NetworkManager.LocalClientId); - - // Assure we are denied ownership due to it requiring ownership be requested - Assert.IsTrue(firstInstanceHelper.OwnershipPermissionsFailureStatus == NetworkObject.OwnershipPermissionsFailureStatus.RequestRequired, - $"Expected {secondInstance.name} to return {NetworkObject.OwnershipPermissionsFailureStatus.RequestRequired} but its permission failure" + - $" status is {secondInstanceHelper.OwnershipPermissionsFailureStatus}!"); - - ////////////////////////////////// - // Test for single race condition: - ////////////////////////////////// - - // Start with a request for the client we expect to be given ownership - var requestStatus = firstInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{firstInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - - // Get the 3rd client to send a request at the "relatively" same time - var thirdInstance = m_ClientNetworkManagers[2].SpawnManager.SpawnedObjects[networkObjectId]; - var thirdInstanceHelper = thirdInstance.GetComponent(); - - // At the same time send a request by the third client. - requestStatus = thirdInstance.RequestOwnership(); - - // We expect the 3rd client's request should be able to be sent at this time as well (i.e. creates the race condition between two clients) - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{m_ServerNetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - - // We expect the first requesting client to be given ownership - yield return WaitForConditionOrTimeOut(() => firstInstance.IsOwner); - AssertOnTimeout($"[Acquire Ownership Failed] Client-{firstInstance.NetworkManager.LocalClientId} failed to get ownership! ({firstInstanceHelper.OwnershipRequestResponseStatus})(Owner: {OwnershipPermissionsTestHelper.CurrentOwnedInstance.OwnerClientId}"); - m_ObjectToValidate = OwnershipPermissionsTestHelper.CurrentOwnedInstance; - - // Just do a sanity check to assure ownership has changed on all clients. - yield return WaitForConditionOrTimeOut(() => ValidateAllInstancesAreOwnedByClient(firstInstance.NetworkManager.LocalClientId)); - AssertOnTimeout($"[Ownership Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - // Now, the third client should get a RequestInProgress returned as their request response - yield return WaitForConditionOrTimeOut(() => thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.RequestInProgress); - AssertOnTimeout($"[Request In Progress Failed] Client-{thirdInstanceHelper.NetworkManager.LocalClientId} did not get the right request denied reponse!"); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Unlock][Permissions Mismatch] {firstInstance.name}: \n {m_ErrorLog}"); - - /////////////////////////////////////////////// - // Test for multiple ownership race conditions: - /////////////////////////////////////////////// - - // Get the 4th client's instance - var fourthInstance = m_ClientNetworkManagers[3].SpawnManager.SpawnedObjects[networkObjectId]; - var fourthInstanceHelper = fourthInstance.GetComponent(); - - // Send out a request from three clients at the same time - // The first one sent (and received for this test) gets ownership - requestStatus = secondInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{secondInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - requestStatus = thirdInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{thirdInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - requestStatus = fourthInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{fourthInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - - // The 2nd and 3rd client should be denied and the 4th client should be approved - yield return WaitForConditionOrTimeOut(() => - (fourthInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.RequestInProgress) && - (thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.RequestInProgress) && - (secondInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Approved) - ); - AssertOnTimeout($"[Targeted Owner] Client-{secondInstanceHelper.NetworkManager.LocalClientId} did not get the right request denied reponse: {secondInstanceHelper.OwnershipRequestResponseStatus}!"); - m_ObjectToValidate = OwnershipPermissionsTestHelper.CurrentOwnedInstance; - // Just do a sanity check to assure ownership has changed on all clients. - yield return WaitForConditionOrTimeOut(() => ValidateAllInstancesAreOwnedByClient(secondInstance.NetworkManager.LocalClientId)); - AssertOnTimeout($"[Ownership Mismatch] {secondInstance.name}: \n {m_ErrorLog}"); - - // Validate the persmissions value for all instances are the same. - yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients); - AssertOnTimeout($"[Unlock][Permissions Mismatch] {secondInstance.name}: \n {m_ErrorLog}"); - - /////////////////////////////////////////////// - // Test for targeted ownership request: - /////////////////////////////////////////////// - - // Now get the DAHost's client's instance - var daHostInstance = m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId]; - var daHostInstanceHelper = daHostInstance.GetComponent(); - - secondInstanceHelper.AllowOwnershipRequest = true; - secondInstanceHelper.OnlyAllowTargetClientId = true; - secondInstanceHelper.ClientToAllowOwnership = daHostInstance.NetworkManager.LocalClientId; - - // Send out a request from all three clients - requestStatus = firstInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{firstInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - requestStatus = thirdInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{thirdInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - requestStatus = fourthInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{fourthInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - requestStatus = daHostInstance.RequestOwnership(); - Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{daHostInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!"); - - // The server and the 2nd client should be denied and the third client should be approved - yield return WaitForConditionOrTimeOut(() => - (firstInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) && - (thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) && - (fourthInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) && - (daHostInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Approved) - ); - AssertOnTimeout($"[Targeted Owner] Client-{daHostInstance.NetworkManager.LocalClientId} did not get the right request reponse: {daHostInstanceHelper.OwnershipRequestResponseStatus} Expecting: {NetworkObject.OwnershipRequestResponseStatus.Approved}!"); - } - - internal class OwnershipPermissionsTestHelper : NetworkBehaviour - { - public static NetworkObject CurrentOwnedInstance; - - public static Dictionary>> DistributedObjects = new Dictionary>>(); - - public bool AllowOwnershipRequest = true; - public bool OnlyAllowTargetClientId = false; - public ulong ClientToAllowOwnership; - - public NetworkObject.OwnershipRequestResponseStatus OwnershipRequestResponseStatus { get; private set; } - - public NetworkObject.OwnershipPermissionsFailureStatus OwnershipPermissionsFailureStatus { get; private set; } - - public NetworkObject.OwnershipRequestResponseStatus ExpectOwnershipRequestResponseStatus { get; set; } - - public override void OnNetworkSpawn() - { - NetworkObject.OnOwnershipRequested = OnOwnershipRequested; - NetworkObject.OnOwnershipRequestResponse = OnOwnershipRequestResponse; - NetworkObject.OnOwnershipPermissionsFailure = OnOwnershipPermissionsFailure; - - base.OnNetworkSpawn(); - } - - private bool OnOwnershipRequested(ulong clientId) - { - // If we are not allowing any client to request (without locking), then deny all requests - if (!AllowOwnershipRequest) - { - return false; - } - - // If we are only allowing a specific client and the requesting client is not the target, - // then deny the request - if (OnlyAllowTargetClientId && clientId != ClientToAllowOwnership) - { - return false; - } - - // Otherwise, approve the request - return true; - } - - private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus) - { - OwnershipRequestResponseStatus = ownershipRequestResponseStatus; - } - - private void OnOwnershipPermissionsFailure(NetworkObject.OwnershipPermissionsFailureStatus ownershipPermissionsFailureStatus) - { - OwnershipPermissionsFailureStatus = ownershipPermissionsFailureStatus; - } - - public override void OnNetworkDespawn() - { - NetworkObject.OnOwnershipRequested = null; - NetworkObject.OnOwnershipRequestResponse = null; - base.OnNetworkSpawn(); - } - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - if (current == NetworkManager.LocalClientId) - { - CurrentOwnedInstance = NetworkObject; - } - base.OnOwnershipChanged(previous, current); - } - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs.meta b/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs.meta deleted file mode 100644 index 392a011..0000000 --- a/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f35119aec96feb348a49b8e0fcd779de -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs b/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs deleted file mode 100644 index 9a7a9f8..0000000 --- a/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// This test validates PR-3000 where it would invoke - /// TODO: - /// We really need to get the service running during tests - /// so we can validate these issues. While this test does - /// partially validate it we still need to manually validate - /// with a service connection. - /// - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.DAHost)] - public class RpcProxyMessageTesting : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private List m_ProxyTestInstances = new List(); - - private StringBuilder m_ValidationLogger = new StringBuilder(); - - public RpcProxyMessageTesting(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override IEnumerator OnSetup() - { - m_ProxyTestInstances.Clear(); - return base.OnSetup(); - } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - base.OnCreatePlayerPrefab(); - } - - - private bool ValidateRpcProxyRpcs() - { - m_ValidationLogger.Clear(); - foreach (var proxy in m_ProxyTestInstances) - { - if (proxy.ReceivedRpc.Count < NumberOfClients) - { - m_ValidationLogger.AppendLine($"Not all clients received RPC from Client-{proxy.OwnerClientId}!"); - } - foreach (var clientId in proxy.ReceivedRpc) - { - if (clientId == proxy.OwnerClientId) - { - m_ValidationLogger.AppendLine($"Client-{proxy.OwnerClientId} sent itself an Rpc!"); - } - } - } - return m_ValidationLogger.Length == 0; - } - - - public IEnumerator ProxyDoesNotInvokeOnSender() - { - m_ProxyTestInstances.Add(m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent()); - foreach (var client in m_ClientNetworkManagers) - { - m_ProxyTestInstances.Add(client.LocalClient.PlayerObject.GetComponent()); - } - - foreach (var clientProxyTest in m_ProxyTestInstances) - { - clientProxyTest.SendToEveryOneButMe(); - } - - yield return WaitForConditionOrTimeOut(ValidateRpcProxyRpcs); - AssertOnTimeout(m_ValidationLogger.ToString()); - } - - public class RpcProxyText : NetworkBehaviour - { - public List ReceivedRpc = new List(); - - public void SendToEveryOneButMe() - { - var baseTarget = NetworkManager.DistributedAuthorityMode ? RpcTarget.NotAuthority : RpcTarget.NotMe; - TestRpc(baseTarget); - } - - [Rpc(SendTo.SpecifiedInParams)] - private void TestRpc(RpcParams rpcParams = default) - { - ReceivedRpc.Add(rpcParams.Receive.SenderClientId); - } - } - } -} diff --git a/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs.meta b/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs.meta deleted file mode 100644 index a877e82..0000000 --- a/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 22d1d751fe245f7419f8393090c27106 \ No newline at end of file diff --git a/Tests/Runtime/HiddenVariableTests.cs b/Tests/Runtime/HiddenVariableTests.cs deleted file mode 100644 index 94b44cf..0000000 --- a/Tests/Runtime/HiddenVariableTests.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class HiddenVariableTest : NetworkBehaviour - { - } - - internal class HiddenVariableObject : NetworkBehaviour - { - public static List ClientInstancesSpawned = new List(); - - public NetworkVariable MyNetworkVariable = new NetworkVariable(); - public NetworkList MyNetworkList = new NetworkList(); - - public static Dictionary ValueOnClient = new Dictionary(); - public static int ExpectedSize = 0; - public static int SpawnCount = 0; - - public static bool EnableVerbose; - - public static void VerboseDebug(string message) - { - if (!EnableVerbose) - { - return; - } - Debug.Log(message); - } - - public override void OnNetworkSpawn() - { - if (!IsServer) - { - ClientInstancesSpawned.Add(NetworkObject); - } - VerboseDebug($"{nameof(HiddenVariableObject)}.{nameof(OnNetworkSpawn)}() with value {MyNetworkVariable.Value}"); - - MyNetworkVariable.OnValueChanged += Changed; - MyNetworkList.OnListChanged += ListChanged; - SpawnCount++; - - base.OnNetworkSpawn(); - } - - public override void OnNetworkDespawn() - { - if (!IsServer) - { - ClientInstancesSpawned.Remove(NetworkObject); - } - base.OnNetworkDespawn(); - } - - public void Changed(int before, int after) - { - VerboseDebug($"[Client-{NetworkManager.LocalClientId}][{name}][MyNetworkVariable] Value changed from {before} to {after}"); - ValueOnClient[NetworkManager.LocalClientId] = after; - } - public void ListChanged(NetworkListEvent listEvent) - { - VerboseDebug($"[Client-{NetworkManager.LocalClientId}][{name}][MyNetworkList] ListEvent received: type {listEvent.Type}, index {listEvent.Index}, value {listEvent.Value}"); - Debug.Assert(ExpectedSize == MyNetworkList.Count, $"[{name}] List change failure! Expected Count: {ExpectedSize} Actual Count:{MyNetworkList.Count}"); - } - } - - internal class HiddenVariableTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 4; - - private NetworkObject m_NetSpawnedObject; - private List m_NetSpawnedObjectOnClient = new List(); - private GameObject m_TestNetworkPrefab; - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - protected override void OnServerAndClientsCreated() - { - m_TestNetworkPrefab = CreateNetworkObjectPrefab("MyTestObject"); - m_TestNetworkPrefab.AddComponent(); - } - - public IEnumerator WaitForSpawnCount(int targetCount) - { - var endTime = Time.realtimeSinceStartup + 1.0; - while (HiddenVariableObject.SpawnCount != targetCount && - Time.realtimeSinceStartup < endTime) - { - yield return new WaitForSeconds(0.01f); - } - } - - public bool VerifyLists() - { - NetworkList prev = null; - int numComparison = 0; - var prevObject = (NetworkObject)null; - // for all the instances of NetworkList - foreach (var networkObject in m_NetSpawnedObjectOnClient) - { - // this skips despawned/hidden objects - if (networkObject != null) - { - // if we've seen another one before - if (prev != null) - { - var curr = networkObject.GetComponent().MyNetworkList; - - // check that the two lists are identical - if (curr.Count != prev.Count) - { - return false; - } - for (int index = 0; index < curr.Count; index++) - { - if (curr[index] != prev[index]) - { - return false; - } - } - numComparison++; - } - prevObject = networkObject; - // store the list - prev = networkObject.GetComponent().MyNetworkList; - } - } - return true; - } - - public IEnumerator RefreshGameObects(int numberToExpect) - { - yield return WaitForConditionOrTimeOut(() => numberToExpect == HiddenVariableObject.ClientInstancesSpawned.Count); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for total spawned count to reach {numberToExpect} but is currently {HiddenVariableObject.ClientInstancesSpawned.Count}"); - m_NetSpawnedObjectOnClient = HiddenVariableObject.ClientInstancesSpawned; - } - - private bool CheckValueOnClient(ulong otherClientId, int value) - { - foreach (var id in m_ServerNetworkManager.ConnectedClientsIds) - { - if (id != otherClientId) - { - if (!HiddenVariableObject.ValueOnClient.ContainsKey(id) || HiddenVariableObject.ValueOnClient[id] != value) - { - return false; - } - } - } - return true; - } - - private IEnumerator SetAndCheckValueSet(ulong otherClientId, int value) - { - yield return WaitForConditionOrTimeOut(() => CheckValueOnClient(otherClientId, value)); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all clients to have a value of {value}"); - - yield return WaitForConditionOrTimeOut(VerifyLists); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for all clients to have identical values!"); - - VerboseDebug("Value changed"); - } - - [UnityTest] - public IEnumerator HiddenVariableTest() - { - HiddenVariableObject.EnableVerbose = m_EnableVerboseDebug; - HiddenVariableObject.SpawnCount = 0; - HiddenVariableObject.ValueOnClient.Clear(); - HiddenVariableObject.ExpectedSize = 0; - HiddenVariableObject.SpawnCount = 0; - - VerboseDebug("Running test"); - - // ==== Spawn object with ownership on one client - var client = m_ServerNetworkManager.ConnectedClientsList[1]; - var otherClient = m_ServerNetworkManager.ConnectedClientsList[2]; - m_NetSpawnedObject = SpawnObject(m_TestNetworkPrefab, m_ClientNetworkManagers[1]).GetComponent(); - - yield return RefreshGameObects(NumberOfClients); - - // === Check spawn occurred - yield return WaitForSpawnCount(NumberOfClients + 1); - - AssertOnTimeout($"Timed out waiting for all clients to spawn {m_NetSpawnedObject.name}"); - - Debug.Assert(HiddenVariableObject.SpawnCount == NumberOfClients + 1); - VerboseDebug("Objects spawned"); - - // ==== Set the NetworkVariable value to 2 - HiddenVariableObject.ExpectedSize = 1; - HiddenVariableObject.SpawnCount = 0; - var currentValueSet = 2; - - m_NetSpawnedObject.GetComponent().MyNetworkVariable.Value = currentValueSet; - m_NetSpawnedObject.GetComponent().MyNetworkList.Add(currentValueSet); - - yield return SetAndCheckValueSet(otherClient.ClientId, currentValueSet); - - // ==== Hide our object to a different client - HiddenVariableObject.ExpectedSize = 2; - m_NetSpawnedObject.NetworkHide(otherClient.ClientId); - currentValueSet = 3; - m_NetSpawnedObject.GetComponent().MyNetworkVariable.Value = currentValueSet; - m_NetSpawnedObject.GetComponent().MyNetworkList.Add(currentValueSet); - - yield return SetAndCheckValueSet(otherClient.ClientId, currentValueSet); - - // ==== Show our object again to this client - HiddenVariableObject.ExpectedSize = 3; - m_NetSpawnedObject.NetworkShow(otherClient.ClientId); - - // ==== Wait for object to be spawned - yield return WaitForSpawnCount(1); - Debug.Assert(HiddenVariableObject.SpawnCount == 1); - VerboseDebug("Object spawned"); - - // ==== We need a refresh for the newly re-spawned object - yield return RefreshGameObects(NumberOfClients); - - currentValueSet = 4; - m_NetSpawnedObject.GetComponent().MyNetworkVariable.Value = currentValueSet; - m_NetSpawnedObject.GetComponent().MyNetworkList.Add(currentValueSet); - - yield return SetAndCheckValueSet(otherClient.ClientId, currentValueSet); - - // ==== Hide our object to that different client again, and then destroy it - m_NetSpawnedObject.NetworkHide(otherClient.ClientId); - yield return new WaitForSeconds(0.2f); - m_NetSpawnedObject.Despawn(); - yield return new WaitForSeconds(0.2f); - } - } -} diff --git a/Tests/Runtime/HiddenVariableTests.cs.meta b/Tests/Runtime/HiddenVariableTests.cs.meta deleted file mode 100644 index 87cfb81..0000000 --- a/Tests/Runtime/HiddenVariableTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c64eb7c36fc44eadac730241b23e006 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/IntegrationTestExamples.cs b/Tests/Runtime/IntegrationTestExamples.cs deleted file mode 100644 index 0318e79..0000000 --- a/Tests/Runtime/IntegrationTestExamples.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class IntegrationTestUpdated : NetcodeIntegrationTest - { - private GameObject m_MyNetworkPrefab; - protected override int NumberOfClients => 1; - - protected override void OnServerAndClientsCreated() - { - m_MyNetworkPrefab = CreateNetworkObjectPrefab("Object"); - m_MyNetworkPrefab.AddComponent(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - SpawnObject(m_MyNetworkPrefab, m_ServerNetworkManager); - yield return base.OnServerAndClientsConnected(); - } - - [UnityTest] - public IEnumerator MyFirstIntegationTest() - { - // Check the condition for this test and automatically handle varying processing - // environments and conditions -#if UNITY_2023_1_OR_NEWER - yield return WaitForConditionOrTimeOut(() => - Object.FindObjectsByType(FindObjectsSortMode.None).Where( - (c) => c.IsSpawned).Count() == 2); -#else - yield return WaitForConditionOrTimeOut(() => - Object.FindObjectsOfType().Where( - (c) => c.IsSpawned).Count() == 2); -#endif - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " + - "to be detected!"); - } - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class IntegrationTestExtended : NetcodeIntegrationTest - { - private GameObject m_MyNetworkPrefab; - protected override int NumberOfClients => 1; - - protected override void OnServerAndClientsCreated() - { - m_MyNetworkPrefab = CreateNetworkObjectPrefab("Object"); - m_MyNetworkPrefab.AddComponent(); - } - - public IntegrationTestExtended(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override IEnumerator OnServerAndClientsConnected() - { - SpawnObject(m_MyNetworkPrefab, m_ServerNetworkManager); - yield return base.OnServerAndClientsConnected(); - } - - [UnityTest] - public IEnumerator MyFirstIntegationTest() - { - // Check the condition for this test and automatically handle varying processing - // environments and conditions -#if UNITY_2023_1_OR_NEWER - yield return WaitForConditionOrTimeOut(() => - Object.FindObjectsByType(FindObjectsSortMode.None).Where( - (c) => c.IsSpawned).Count() == 2); -#else - yield return WaitForConditionOrTimeOut(() => - Object.FindObjectsOfType().Where( - (c) => c.IsSpawned).Count() == 2); -#endif - - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " + - "to be detected!"); - } - } - - internal class ExampleTestComponent : NetworkBehaviour - { - } - - internal class IntegrationTestPlayers : NetcodeIntegrationTest - { - protected override int NumberOfClients => 5; - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - return base.OnServerAndClientsConnected(); - } - - [Test] - public void TestClientRelativePlayers() - { - // Check that all instances have the ExampleTestComponent - foreach (var clientRelativePlayers in m_PlayerNetworkObjects) - { - foreach (var playerInstance in clientRelativePlayers.Value) - { - var player = playerInstance.Value; - Assert.NotNull(player.GetComponent()); - } - } - - // Confirm Player ID 1 on Client ID 4 is not the local player - Assert.IsFalse(m_PlayerNetworkObjects[4][1].IsLocalPlayer); - // Confirm Player ID 4 on Client ID 4 is the local player - Assert.IsTrue(m_PlayerNetworkObjects[4][4].IsLocalPlayer); - // Confirm Player ID 0 on Client ID 0 (host) NetworkManager is the server - Assert.IsTrue(m_PlayerNetworkObjects[0][0].NetworkManager.IsServer); - // Confirm Player ID 0 on Client ID 4 (client) NetworkManager is not the server - Assert.IsFalse(m_PlayerNetworkObjects[4][0].NetworkManager.IsServer); - } - } - - internal class SpawnTest : NetworkBehaviour - { - public static int TotalSpawned; - public override void OnNetworkSpawn() { TotalSpawned++; } - public override void OnNetworkDespawn() { TotalSpawned--; } - } - internal class IntegrationTestSpawning : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - private GameObject m_NetworkPrefabToSpawn; - private int m_NumberToSpawn = 5; - - protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() - { - return NetworkManagerInstatiationMode.AllTests; - } - - protected override void OnServerAndClientsCreated() - { - m_NetworkPrefabToSpawn = CreateNetworkObjectPrefab("TrackingTest"); - m_NetworkPrefabToSpawn.gameObject.AddComponent(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - SpawnObjects(m_NetworkPrefabToSpawn, m_ServerNetworkManager, m_NumberToSpawn); - return base.OnServerAndClientsConnected(); - } - - [UnityTest] - [Order(1)] - public IEnumerator TestRelativeNetworkObjects() - { - var expected = m_NumberToSpawn * TotalClients; - // Wait for all clients to have spawned all instances - yield return WaitForConditionOrTimeOut(() => SpawnTest.TotalSpawned == expected); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all to " + - $"spawn! Total Spawned: {SpawnTest.TotalSpawned}"); - - var client1Relative = s_GlobalNetworkObjects[1].Values.Where((c) => - c.gameObject.GetComponent() != null); - foreach (var networkObject in client1Relative) - { - var testComp = networkObject.GetComponent(); - // Confirm each one is owned by the server - Assert.IsTrue(testComp.IsOwnedByServer, $"{testComp.name} is not owned" + - $" by the server!"); - } - } - - [UnityTest] - [Order(2)] - public IEnumerator TestDespawnNetworkObjects() - { - var serverRelative = s_GlobalNetworkObjects[0].Values.Where((c) => - c.gameObject.GetComponent() != null).ToList(); - foreach (var networkObject in serverRelative) - { - networkObject.Despawn(); - } - // Wait for all clients to have spawned all instances - yield return WaitForConditionOrTimeOut(() => SpawnTest.TotalSpawned == 0); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all to " + - $"despawn! Total Spawned: {SpawnTest.TotalSpawned}"); - } - } -} diff --git a/Tests/Runtime/IntegrationTestExamples.cs.meta b/Tests/Runtime/IntegrationTestExamples.cs.meta deleted file mode 100644 index d0c1c99..0000000 --- a/Tests/Runtime/IntegrationTestExamples.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5a64e8d7b2082a9409b53f83d0c4e537 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/InvalidConnectionEventsTest.cs b/Tests/Runtime/InvalidConnectionEventsTest.cs deleted file mode 100644 index d849bc2..0000000 --- a/Tests/Runtime/InvalidConnectionEventsTest.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Debug = UnityEngine.Debug; - -namespace Unity.Netcode.RuntimeTests -{ - internal class InvalidConnectionEventsTest : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - public InvalidConnectionEventsTest() : base(HostOrServer.Server) { } - - private class Hooks : INetworkHooks - { - public void OnBeforeSendMessage(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage - { - } - - public void OnAfterSendMessage(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage - { - } - - public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - public void OnAfterReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - public void OnBeforeSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - public void OnAfterSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - public void OnBeforeReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - public void OnAfterReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - public bool OnVerifyCanSend(ulong destinationId, Type messageType, NetworkDelivery delivery) - { - return true; - } - - public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReader messageContent, ref NetworkContext context) - { - return true; - } - - public void OnBeforeHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - if (typeof(T) == typeof(TCatchType)) - { - Debug.Log("Woompa"); - Assert.Fail($"{typeof(T).Name} was received when it should not have been."); - } - } - - public void OnAfterHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - } - - [UnityTest] - public IEnumerator WhenSendingConnectionApprovedToAlreadyConnectedClient_ConnectionApprovedMessageIsRejected() - { - var message = new ConnectionApprovedMessage - { - ConnectedClientIds = new NativeArray(0, Allocator.Temp) - }; - m_ServerNetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.Reliable, m_ClientNetworkManagers[0].LocalClientId); - - // Unnamed message is something to wait for. When this one is received, - // we know the above one has also reached its destination. - var writer = new FastBufferWriter(1, Allocator.Temp); - using (writer) - { - writer.WriteByteSafe(0); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(m_ClientNetworkManagers[0].LocalClientId, writer); - } - - m_ClientNetworkManagers[0].ConnectionManager.MessageManager.Hook(new Hooks()); - - LogAssert.Expect(LogType.Error, new Regex($"A {nameof(ConnectionApprovedMessage)} was received from the server when the connection has already been established\\. NetworkTransport: Unity.Netcode.Transports.UTP.UnityTransport UnityTransportProtocol: UnityTransport. This should not happen\\.")); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - } - - [UnityTest] - public IEnumerator WhenSendingConnectionRequestToAnyClient_ConnectionRequestMessageIsRejected() - { - var message = new ConnectionRequestMessage(); - m_ServerNetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.Reliable, m_ClientNetworkManagers[0].LocalClientId); - - // Unnamed message is something to wait for. When this one is received, - // we know the above one has also reached its destination. - var writer = new FastBufferWriter(1, Allocator.Temp); - using (writer) - { - writer.WriteByteSafe(0); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(m_ClientNetworkManagers[0].LocalClientId, writer); - } - - m_ClientNetworkManagers[0].ConnectionManager.MessageManager.Hook(new Hooks()); - - LogAssert.Expect(LogType.Error, new Regex($"A {nameof(ConnectionRequestMessage)} was received from the server on the client side\\. NetworkTransport: Unity.Netcode.Transports.UTP.UnityTransport UnityTransportProtocol: UnityTransport. This should not happen\\.")); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - } - - [UnityTest] - public IEnumerator WhenSendingConnectionRequestFromAlreadyConnectedClient_ConnectionRequestMessageIsRejected() - { - var message = new ConnectionRequestMessage(); - m_ClientNetworkManagers[0].ConnectionManager.SendMessage(ref message, NetworkDelivery.Reliable, m_ServerNetworkManager.LocalClientId); - - // Unnamed message is something to wait for. When this one is received, - // we know the above one has also reached its destination. - var writer = new FastBufferWriter(1, Allocator.Temp); - using (writer) - { - writer.WriteByteSafe(0); - m_ClientNetworkManagers[0].CustomMessagingManager.SendUnnamedMessage(m_ServerNetworkManager.LocalClientId, writer); - } - - m_ServerNetworkManager.ConnectionManager.MessageManager.Hook(new Hooks()); - - LogAssert.Expect(LogType.Error, new Regex($"A {nameof(ConnectionRequestMessage)} was received from a client when the connection has already been established\\. NetworkTransport: Unity.Netcode.Transports.UTP.UnityTransport UnityTransportProtocol: UnityTransport. This should not happen\\.")); - - yield return WaitForMessageReceived(new List { m_ServerNetworkManager }); - } - - [UnityTest] - public IEnumerator WhenSendingConnectionApprovedFromAnyClient_ConnectionApprovedMessageIsRejected() - { - var message = new ConnectionApprovedMessage - { - ConnectedClientIds = new NativeArray(0, Allocator.Temp) - }; - m_ClientNetworkManagers[0].ConnectionManager.SendMessage(ref message, NetworkDelivery.Reliable, m_ServerNetworkManager.LocalClientId); - - // Unnamed message is something to wait for. When this one is received, - // we know the above one has also reached its destination. - var writer = new FastBufferWriter(1, Allocator.Temp); - using (writer) - { - writer.WriteByteSafe(0); - m_ClientNetworkManagers[0].CustomMessagingManager.SendUnnamedMessage(m_ServerNetworkManager.LocalClientId, writer); - } - - m_ServerNetworkManager.ConnectionManager.MessageManager.Hook(new Hooks()); - - LogAssert.Expect(LogType.Error, new Regex($"A {nameof(ConnectionApprovedMessage)} was received from a client on the server side\\. NetworkTransport: Unity.Netcode.Transports.UTP.UnityTransport UnityTransportProtocol: UnityTransport. This should not happen\\.")); - - yield return WaitForMessageReceived(new List { m_ServerNetworkManager }); - } - } -} diff --git a/Tests/Runtime/InvalidConnectionEventsTest.cs.meta b/Tests/Runtime/InvalidConnectionEventsTest.cs.meta deleted file mode 100644 index b9c2b32..0000000 --- a/Tests/Runtime/InvalidConnectionEventsTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c30dd8c697274dd195f0fa8b86a4cf9d -timeCreated: 1677003739 \ No newline at end of file diff --git a/Tests/Runtime/ListChangedTest.cs b/Tests/Runtime/ListChangedTest.cs deleted file mode 100644 index 3f47ae9..0000000 --- a/Tests/Runtime/ListChangedTest.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkListChangedTestComponent : NetworkBehaviour - { - - } - - internal class ListChangedObject : NetworkBehaviour - { - public int ExpectedPreviousValue = 0; - public int ExpectedValue = 0; - public bool AddDone = false; - - public NetworkList MyNetworkList = new NetworkList(); - - public override void OnNetworkSpawn() - { - MyNetworkList.OnListChanged += Changed; - base.OnNetworkSpawn(); - } - - public void Changed(NetworkListEvent listEvent) - { - if (listEvent.Type == NetworkListEvent.EventType.Value) - { - if (listEvent.PreviousValue != ExpectedPreviousValue) - { - Debug.Log($"Expected previous value mismatch {listEvent.PreviousValue} versus {ExpectedPreviousValue}"); - Debug.Assert(listEvent.PreviousValue == ExpectedPreviousValue); - } - - if (listEvent.Value != ExpectedValue) - { - Debug.Log($"Expected value mismatch {listEvent.Value} versus {ExpectedValue}"); - Debug.Assert(listEvent.Value == ExpectedValue); - } - - AddDone = true; - } - } - } - - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(NetworkTopologyTypes.ClientServer)] - internal class NetworkListChangedTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private ulong m_ClientId0; - private GameObject m_PrefabToSpawn; - - private NetworkObject m_NetSpawnedObject1; - - public NetworkListChangedTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("ListChangedObject"); - m_PrefabToSpawn.AddComponent(); - } - - [UnityTest] - public IEnumerator NetworkListChangedTest() - { - m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; - - // create 3 objects - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - - m_NetSpawnedObject1.GetComponent().MyNetworkList.Add(42); - m_NetSpawnedObject1.GetComponent().ExpectedPreviousValue = 42; - m_NetSpawnedObject1.GetComponent().ExpectedValue = 44; - m_NetSpawnedObject1.GetComponent().MyNetworkList[0] = 44; - - Debug.Assert(m_NetSpawnedObject1.GetComponent().AddDone); - - return null; - } - } -} diff --git a/Tests/Runtime/ListChangedTest.cs.meta b/Tests/Runtime/ListChangedTest.cs.meta deleted file mode 100644 index 1cc34f6..0000000 --- a/Tests/Runtime/ListChangedTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b269e2a059f814075a737691bc02afa4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Messaging.meta b/Tests/Runtime/Messaging.meta deleted file mode 100644 index bb30551..0000000 --- a/Tests/Runtime/Messaging.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 60efb82fa0154d6caf94fea440f167d4 -timeCreated: 1627407732 \ No newline at end of file diff --git a/Tests/Runtime/Messaging/DisconnectReasonTests.cs b/Tests/Runtime/Messaging/DisconnectReasonTests.cs deleted file mode 100644 index e293be3..0000000 --- a/Tests/Runtime/Messaging/DisconnectReasonTests.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections; -using System.Text.RegularExpressions; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class DisconnectReasonObject : NetworkBehaviour - { - - } - - internal class DisconnectReasonTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private GameObject m_PrefabToSpawn; - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("DisconnectReasonObject"); - m_PrefabToSpawn.AddComponent(); - } - - private int m_DisconnectCount; - private bool m_ThrowOnDisconnect = false; - - public void OnClientDisconnectCallback(ulong clientId) - { - m_DisconnectCount++; - if (m_ThrowOnDisconnect) - { - throw new SystemException("whatever"); - } - } - - [UnityTest] - public IEnumerator DisconnectReasonTest() - { - float startTime = Time.realtimeSinceStartup; - m_ThrowOnDisconnect = false; - m_DisconnectCount = 0; - - // Add a callback for both clients, when they get disconnected - m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback; - m_ClientNetworkManagers[1].OnClientDisconnectCallback += OnClientDisconnectCallback; - - // Disconnect both clients, from the server - m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[0].LocalClientId, "Bogus reason 1"); - m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[1].LocalClientId, "Bogus reason 2"); - - while (m_DisconnectCount < 2 && Time.realtimeSinceStartup < startTime + 10.0f) - { - yield return null; - } - - Assert.AreEqual(m_ClientNetworkManagers[0].DisconnectReason, "Bogus reason 1"); - Assert.AreEqual(m_ClientNetworkManagers[1].DisconnectReason, "Bogus reason 2"); - - Debug.Assert(m_DisconnectCount == 2); - } - - [UnityTest] - public IEnumerator DisconnectExceptionTest() - { - m_ThrowOnDisconnect = true; - m_DisconnectCount = 0; - float startTime = Time.realtimeSinceStartup; - - // Add a callback for first client, when they get disconnected - m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback; - m_ClientNetworkManagers[1].OnClientDisconnectCallback += OnClientDisconnectCallback; - - // Disconnect first client, from the server - LogAssert.Expect(LogType.Exception, new Regex(".*whatever.*")); - m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[0].LocalClientId); - - // Disconnect second client, from the server - LogAssert.Expect(LogType.Exception, new Regex(".*whatever.*")); - m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[1].LocalClientId); - - while (m_DisconnectCount < 2 && Time.realtimeSinceStartup < startTime + 10.0f) - { - yield return null; - } - - Debug.Assert(m_DisconnectCount == 2); - } - } -} diff --git a/Tests/Runtime/Messaging/DisconnectReasonTests.cs.meta b/Tests/Runtime/Messaging/DisconnectReasonTests.cs.meta deleted file mode 100644 index 26b12ef..0000000 --- a/Tests/Runtime/Messaging/DisconnectReasonTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 93141fa15824f406b89dbc6f32c8910d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Messaging/NamedMessageTests.cs b/Tests/Runtime/Messaging/NamedMessageTests.cs deleted file mode 100644 index 4c2d0d8..0000000 --- a/Tests/Runtime/Messaging/NamedMessageTests.cs +++ /dev/null @@ -1,283 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NamedMessageTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private NetworkManager FirstClient => m_ClientNetworkManagers[0]; - private NetworkManager SecondClient => m_ClientNetworkManagers[1]; - - protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() - { - // Don't spin up and shutdown NetworkManager instances for each test - // within this set of integration tests. - return NetworkManagerInstatiationMode.AllTests; - } - - [UnityTest] - public IEnumerator NamedMessageIsReceivedOnClientWithContent() - { - var messageName = Guid.NewGuid().ToString(); - - ulong receivedMessageSender = 0; - var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - receivedMessageSender = sender; - - reader.ReadValueSafe(out receivedMessageContent); - }); - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( - messageName, - FirstClient.LocalClientId, - writer); - } - - yield return WaitForMessageReceived(new List { FirstClient }); - - Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); - } - - [Test] - public void NamedMessageIsReceivedOnHostWithContent() - { - var messageName = Guid.NewGuid().ToString(); - - ulong receivedMessageSender = 0; - var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - receivedMessageSender = sender; - - reader.ReadValueSafe(out receivedMessageContent); - }); - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( - messageName, - m_ServerNetworkManager.LocalClientId, - writer); - } - - Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); - } - - private void MockNamedMessageCallback(ulong sender, FastBufferReader reader) - { - - } - - [Test] - public void NullOrEmptyNamedMessageDoesNotThrowException() - { - LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.RegisterNamedMessageHandler)}] Cannot register a named message of type null or empty!"); - m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(string.Empty, MockNamedMessageCallback); - LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.RegisterNamedMessageHandler)}] Cannot register a named message of type null or empty!"); - m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(null, MockNamedMessageCallback); - LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.UnregisterNamedMessageHandler)}] Cannot unregister a named message of type null or empty!"); - m_ServerNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(string.Empty); - LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.UnregisterNamedMessageHandler)}] Cannot unregister a named message of type null or empty!"); - m_ServerNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(null); - } - - [UnityTest] - public IEnumerator NamedMessageIsReceivedOnMultipleClientsWithContent() - { - var messageName = Guid.NewGuid().ToString(); - - ulong firstReceivedMessageSender = 0; - var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - firstReceivedMessageSender = sender; - - reader.ReadValueSafe(out firstReceivedMessageContent); - }); - - ulong secondReceivedMessageSender = 0; - var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - SecondClient.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - secondReceivedMessageSender = sender; - - reader.ReadValueSafe(out secondReceivedMessageContent); - }); - - ulong thirdReceivedMessageSender = 0; - var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - thirdReceivedMessageSender = sender; - - reader.ReadValueSafe(out thirdReceivedMessageContent); - }); - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( - messageName, - new List { m_ServerNetworkManager.LocalClientId, FirstClient.LocalClientId, SecondClient.LocalClientId }, - writer); - } - - yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); - - Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); - } - - [UnityTest] - public IEnumerator WhenSendingNamedMessageToAll_AllClientsReceiveIt() - { - var messageName = Guid.NewGuid().ToString(); - - ulong firstReceivedMessageSender = 0; - var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - firstReceivedMessageSender = sender; - - reader.ReadValueSafe(out firstReceivedMessageContent); - }); - - ulong secondReceivedMessageSender = 0; - var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - SecondClient.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - secondReceivedMessageSender = sender; - - reader.ReadValueSafe(out secondReceivedMessageContent); - }); - - ulong thirdReceivedMessageSender = 0; - var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( - messageName, - (ulong sender, FastBufferReader reader) => - { - thirdReceivedMessageSender = sender; - - reader.ReadValueSafe(out thirdReceivedMessageContent); - }); - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessageToAll(messageName, writer); - } - - yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); - - Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); - } - - [Test] - public void WhenSendingNamedMessageToNullClientList_ArgumentNullExceptionIsThrown() - { - var messageName = Guid.NewGuid().ToString(); - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, null, writer); - }); - } - } - - [Test] - public unsafe void ErrorMessageIsPrintedWhenAttemptingToSendNamedMessageWithTooBigBuffer() - { - // First try a valid send with the maximum allowed size (this is atm 1264) - var msgSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize - FastBufferWriter.GetWriteSize() - sizeof(ulong)/*MessageName hash*/ - sizeof(NetworkBatchHeader); - var bufferSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize; - var messageName = Guid.NewGuid().ToString(); - var messageContent = new byte[msgSize]; - var writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); - using (writer) - { - writer.TryBeginWrite(msgSize); - writer.WriteBytes(messageContent, msgSize, 0); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, new List { FirstClient.LocalClientId }, writer); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, FirstClient.LocalClientId, writer); - } - - msgSize++; - messageContent = new byte[msgSize]; - writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); - using (writer) - { - writer.TryBeginWrite(msgSize); - writer.WriteBytes(messageContent, msgSize, 0); - var message = Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, new List { FirstClient.LocalClientId }, writer); - }).Message; - Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); - - message = Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, FirstClient.LocalClientId, writer); - }).Message; - Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); - } - } - } -} diff --git a/Tests/Runtime/Messaging/NamedMessageTests.cs.meta b/Tests/Runtime/Messaging/NamedMessageTests.cs.meta deleted file mode 100644 index 8b7e64e..0000000 --- a/Tests/Runtime/Messaging/NamedMessageTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 50770f69eb9d3604184f918a2d0674e7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Messaging/UnnamedMessageTests.cs b/Tests/Runtime/Messaging/UnnamedMessageTests.cs deleted file mode 100644 index 8b0c854..0000000 --- a/Tests/Runtime/Messaging/UnnamedMessageTests.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class UnnamedMessageTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private NetworkManager FirstClient => m_ClientNetworkManagers[0]; - private NetworkManager SecondClient => m_ClientNetworkManagers[1]; - - [UnityTest] - public IEnumerator UnnamedMessageIsReceivedOnClientWithContent() - { - ulong receivedMessageSender = 0; - var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - receivedMessageSender = sender; - - reader.ReadValueSafe(out receivedMessageContent); - }; - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage( - FirstClient.LocalClientId, - writer); - } - - yield return WaitForMessageReceived(new List { FirstClient }); - - Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); - } - - [Test] - public void UnnamedMessageIsReceivedOnHostWithContent() - { - ulong receivedMessageSender = 0; - var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - receivedMessageSender = sender; - - reader.ReadValueSafe(out receivedMessageContent); - }; - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage( - m_ServerNetworkManager.LocalClientId, - writer); - } - - Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); - } - - [UnityTest] - public IEnumerator UnnamedMessageIsReceivedOnMultipleClientsWithContent() - { - ulong firstReceivedMessageSender = 0; - var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - firstReceivedMessageSender = sender; - - reader.ReadValueSafe(out firstReceivedMessageContent); - }; - - ulong secondReceivedMessageSender = 0; - var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - SecondClient.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - secondReceivedMessageSender = sender; - - reader.ReadValueSafe(out secondReceivedMessageContent); - }; - - ulong thirdReceivedMessageSender = 0; - var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - thirdReceivedMessageSender = sender; - - reader.ReadValueSafe(out thirdReceivedMessageContent); - }; - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage( - new List { m_ServerNetworkManager.LocalClientId, FirstClient.LocalClientId, SecondClient.LocalClientId }, - writer); - } - - yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); - - Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); - } - - [UnityTest] - public IEnumerator WhenSendingUnnamedMessageToAll_AllClientsReceiveIt() - { - ulong firstReceivedMessageSender = 0; - var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - FirstClient.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - firstReceivedMessageSender = sender; - - reader.ReadValueSafe(out firstReceivedMessageContent); - }; - - ulong secondReceivedMessageSender = 0; - var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - SecondClient.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - secondReceivedMessageSender = sender; - - reader.ReadValueSafe(out secondReceivedMessageContent); - }; - - ulong thirdReceivedMessageSender = 0; - var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); - m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage += - (ulong sender, FastBufferReader reader) => - { - thirdReceivedMessageSender = sender; - - reader.ReadValueSafe(out thirdReceivedMessageContent); - }; - - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer); - } - - yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); - - Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); - - Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); - Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); - } - - [Test] - public void WhenSendingNamedMessageToNullClientList_ArgumentNullExceptionIsThrown() - { - var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - using (writer) - { - writer.WriteValueSafe(messageContent); - Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(null, writer); - }); - } - } - - [Test] - public unsafe void ErrorMessageIsPrintedWhenAttemptingToSendUnnamedMessageWithTooBigBuffer() - { - // First try a valid send with the maximum allowed size (this is atm 1272) - var msgSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize - FastBufferWriter.GetWriteSize() - sizeof(NetworkBatchHeader); - var bufferSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize; - var messageContent = new byte[msgSize]; - var writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); - using (writer) - { - writer.TryBeginWrite(msgSize); - writer.WriteBytes(messageContent, msgSize, 0); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(new List { FirstClient.LocalClientId }, writer); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(FirstClient.LocalClientId, writer); - } - - msgSize++; - messageContent = new byte[msgSize]; - writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); - using (writer) - { - writer.TryBeginWrite(msgSize); - writer.WriteBytes(messageContent, msgSize, 0); - var message = Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(new List { FirstClient.LocalClientId }, writer); - }).Message; - Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); - - message = Assert.Throws( - () => - { - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(FirstClient.LocalClientId, writer); - }).Message; - Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); - } - } - } -} diff --git a/Tests/Runtime/Messaging/UnnamedMessageTests.cs.meta b/Tests/Runtime/Messaging/UnnamedMessageTests.cs.meta deleted file mode 100644 index 81b2ef4..0000000 --- a/Tests/Runtime/Messaging/UnnamedMessageTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f5affb61a1b56d44c80d0e2d55cc04aa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics.meta b/Tests/Runtime/Metrics.meta deleted file mode 100644 index 11b63da..0000000 --- a/Tests/Runtime/Metrics.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4cd7fa97c73f3674b9cce18b1e0a6874 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/ConnectionMetricsTests.cs b/Tests/Runtime/Metrics/ConnectionMetricsTests.cs deleted file mode 100644 index b94cc47..0000000 --- a/Tests/Runtime/Metrics/ConnectionMetricsTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -#if MULTIPLAYER_TOOLS -#if MULTIPLAYER_TOOLS_1_0_0_PRE_7 - -using System.Collections; -using NUnit.Framework; -using Unity.Multiplayer.Tools.MetricTypes; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.TestHelpers.Runtime.Metrics; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - [TestFixture(ClientCount.OneClient, HostOrServer.Host)] - [TestFixture(ClientCount.TwoClients, HostOrServer.Host)] - [TestFixture(ClientCount.OneClient, HostOrServer.Server)] - [TestFixture(ClientCount.TwoClients, HostOrServer.Server)] - internal class ConnectionMetricsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => m_ClientCount; - - private int m_ClientCount; - - public enum ClientCount - { - OneClient = 1, - TwoClients, - } - - public ConnectionMetricsTests(ClientCount clientCount, HostOrServer hostOrServer) - : base(hostOrServer) - { - m_ClientCount = (int)clientCount; - } - - private int GetClientCountForFixture() - { - return m_ClientCount + ((m_UseHost) ? 1 : 0); - } - - [UnityTest] - public IEnumerator UpdateConnectionCountOnServer() - { - var waitForGaugeValues = new WaitForGaugeMetricValues((m_ServerNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.ConnectedClients); - - yield return waitForGaugeValues.WaitForMetricsReceived(); - - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(GetClientCountForFixture(), value); - } - - [UnityTest] - public IEnumerator UpdateConnectionCountOnClient() - { - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var waitForGaugeValues = new WaitForGaugeMetricValues((clientNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.ConnectedClients); - - yield return waitForGaugeValues.WaitForMetricsReceived(); - - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(1, value); - } - } - } -} - -#endif -#endif diff --git a/Tests/Runtime/Metrics/ConnectionMetricsTests.cs.meta b/Tests/Runtime/Metrics/ConnectionMetricsTests.cs.meta deleted file mode 100644 index bc0d812..0000000 --- a/Tests/Runtime/Metrics/ConnectionMetricsTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1845aef61dbb4f2b9d2be9145262ab90 -timeCreated: 1647023529 \ No newline at end of file diff --git a/Tests/Runtime/Metrics/MessagingMetricsTests.cs b/Tests/Runtime/Metrics/MessagingMetricsTests.cs deleted file mode 100644 index 6cd827f..0000000 --- a/Tests/Runtime/Metrics/MessagingMetricsTests.cs +++ /dev/null @@ -1,275 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using Unity.Netcode.TestHelpers.Runtime.Metrics; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class MessagingMetricsTests : DualClientMetricTestBase - { - private const uint k_MessageNameHashSize = 8; - // Header is dynamically sized due to packing, will be 2 bytes for all test messages. - private const int k_MessageHeaderSize = 2; - private static readonly int k_NamedMessageOverhead = (int)k_MessageNameHashSize + k_MessageHeaderSize; - private static readonly int k_UnnamedMessageOverhead = k_MessageHeaderSize; - - protected override int NumberOfClients => 2; - - [UnityTest] - public IEnumerator TrackNetworkMessageSentMetric() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent); - - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var networkMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - - // We should have 1 NamedMessage - Assert.That(networkMessageSentMetricValues, Has.Exactly(1).Matches(x => x.Name == nameof(NamedMessage))); - } - - [UnityTest] - public IEnumerator TrackNetworkMessageSentMetricToMultipleClients() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageSent); - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), new List { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer); - } - - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var networkMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, networkMessageSentMetricValues.Count(x => x.Name.Equals(nameof(NamedMessage)))); - } - - [UnityTest] - public IEnumerator TrackNetworkMessageReceivedMetric() - { - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - - LogAssert.Expect(LogType.Log, $"Received from {Server.LocalClientId}"); - FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.Value.ToString(), (ulong sender, FastBufferReader payload) => - { - Debug.Log($"Received from {sender}"); - }); - var waitForMetricValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NetworkMessageReceived, - metric => metric.Name == nameof(NamedMessage)); - - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var networkMessageReceivedValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - // We should have 1 NamedMessage - Assert.That(networkMessageReceivedValues, Has.Exactly(1).Matches(x => x.Name == nameof(NamedMessage))); - } - - [UnityTest] - public IEnumerator TrackNamedMessageSentMetric() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent); - - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer); - } - - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var namedMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, namedMessageSentMetricValues.Count); - - var namedMessageSent = namedMessageSentMetricValues.First(); - Assert.AreEqual(messageName.Value.ToString(), namedMessageSent.Name); - Assert.AreEqual(FirstClient.LocalClientId, namedMessageSent.Connection.Id); - Assert.AreEqual(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead, namedMessageSent.BytesCount); - } - - [UnityTest] - public IEnumerator TrackNamedMessageSentMetricToMultipleClients() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent); - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), new List { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer); - } - - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var namedMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, namedMessageSentMetricValues.Count); - Assert.That(namedMessageSentMetricValues.Select(x => x.Name), Has.All.EqualTo(messageName.Value.ToString())); - Assert.That(namedMessageSentMetricValues.Select(x => x.BytesCount), Has.All.EqualTo(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead)); - } - - [UnityTest] - public IEnumerator TrackNamedMessageSentMetricToSelf() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NamedMessageSent); - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Server.LocalClientId, writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - waitForMetricValues.AssertMetricValuesHaveNotBeenFound(); - } - - [UnityTest] - public IEnumerator TrackNamedMessageReceivedMetric() - { - var waitForMetricValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.NamedMessageReceived); - - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - - LogAssert.Expect(LogType.Log, $"Received from {Server.LocalClientId}"); - FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(messageName.Value.ToString(), (ulong sender, FastBufferReader payload) => - { - Debug.Log($"Received from {sender}"); - }); - - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), FirstClient.LocalClientId, writer); - } - - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var namedMessageReceivedValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, namedMessageReceivedValues.Count); - - var namedMessageReceived = namedMessageReceivedValues.First(); - Assert.AreEqual(messageName.Value.ToString(), namedMessageReceived.Name); - Assert.AreEqual(Server.LocalClientId, namedMessageReceived.Connection.Id); - Assert.AreEqual(FastBufferWriter.GetWriteSize(messageName) + k_NamedMessageOverhead, namedMessageReceived.BytesCount); - } - - [UnityTest] - public IEnumerator TrackUnnamedMessageSentMetric() - { - var message = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(message); - - Server.CustomMessagingManager.SendUnnamedMessage(FirstClient.LocalClientId, writer); - } - - - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var unnamedMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, unnamedMessageSentMetricValues.Count); - - var unnamedMessageSent = unnamedMessageSentMetricValues.First(); - Assert.AreEqual(FirstClient.LocalClientId, unnamedMessageSent.Connection.Id); - Assert.AreEqual(FastBufferWriter.GetWriteSize(message) + k_UnnamedMessageOverhead, unnamedMessageSent.BytesCount); - } - - [UnityTest] - public IEnumerator TrackUnnamedMessageSentMetricToMultipleClients() - { - var message = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(message); - - Server.CustomMessagingManager.SendUnnamedMessage(new List { FirstClient.LocalClientId, SecondClient.LocalClientId }, writer); - } - - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var unnamedMessageSentMetricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, unnamedMessageSentMetricValues.Count); - Assert.That(unnamedMessageSentMetricValues.Select(x => x.BytesCount), Has.All.EqualTo(FastBufferWriter.GetWriteSize(message) + k_UnnamedMessageOverhead)); - - var clientIds = unnamedMessageSentMetricValues.Select(x => x.Connection.Id).ToList(); - Assert.Contains(FirstClient.LocalClientId, clientIds); - Assert.Contains(SecondClient.LocalClientId, clientIds); - } - - [UnityTest] - public IEnumerator TrackUnnamedMessageSentMetricToSelf() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageSent); - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendUnnamedMessage(Server.LocalClientId, writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - waitForMetricValues.AssertMetricValuesHaveNotBeenFound(); - } - - [UnityTest] - public IEnumerator TrackUnnamedMessageReceivedMetric() - { - var message = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var waitForMetricValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.UnnamedMessageReceived); - using (var writer = new FastBufferWriter(1300, Allocator.Temp)) - { - writer.WriteValueSafe(message); - - Server.CustomMessagingManager.SendUnnamedMessage(FirstClient.LocalClientId, writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var unnamedMessageReceivedValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, unnamedMessageReceivedValues.Count); - - var unnamedMessageReceived = unnamedMessageReceivedValues.First(); - Assert.AreEqual(Server.LocalClientId, unnamedMessageReceived.Connection.Id); - Assert.AreEqual(FastBufferWriter.GetWriteSize(message) + k_UnnamedMessageOverhead, unnamedMessageReceived.BytesCount); - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/MessagingMetricsTests.cs.meta b/Tests/Runtime/Metrics/MessagingMetricsTests.cs.meta deleted file mode 100644 index 7910ff2..0000000 --- a/Tests/Runtime/Metrics/MessagingMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2490ed51138306e4d92f8e9dcfc34462 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/MetricsDispatchTests.cs b/Tests/Runtime/Metrics/MetricsDispatchTests.cs deleted file mode 100644 index e8a268c..0000000 --- a/Tests/Runtime/Metrics/MetricsDispatchTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Multiplayer.Tools.NetStats; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class MetricsDispatchTests - { - private int m_NbDispatches; - - private NetworkManager m_NetworkManager; - - [SetUp] - public void SetUp() - { - var networkManagerStarted = NetworkManagerHelper.StartNetworkManager( - out m_NetworkManager, - NetworkManagerHelper.NetworkManagerOperatingMode.Host, - new NetworkConfig - { - TickRate = 1, - }); - Assert.IsTrue(networkManagerStarted); - - var networkMetrics = m_NetworkManager.NetworkMetrics as NetworkMetrics; - networkMetrics.Dispatcher.RegisterObserver(new MockMetricsObserver(() => m_NbDispatches++)); - } - - [TearDown] - public void TearDown() - { - NetworkManagerHelper.ShutdownNetworkManager(); - } - - [UnityTest] - public IEnumerator VerifyNetworkMetricsDispatchesOncePerFrame() - { - var nbDispatchesBeforeFrame = m_NbDispatches; - - yield return null; // Wait one frame so dispatch occurs - - var nbDispatchesAfterFrame = m_NbDispatches; - - Assert.AreEqual(1, nbDispatchesAfterFrame - nbDispatchesBeforeFrame); - } - - private class MockMetricsObserver : IMetricObserver - { - private readonly Action m_OnObserve; - - public MockMetricsObserver(Action onObserve) - { - m_OnObserve = onObserve; - } - - public void Observe(MetricCollection collection) - { - m_OnObserve?.Invoke(); - } - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/MetricsDispatchTests.cs.meta b/Tests/Runtime/Metrics/MetricsDispatchTests.cs.meta deleted file mode 100644 index 9a19940..0000000 --- a/Tests/Runtime/Metrics/MetricsDispatchTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 4833f15c8a59407abbb8532ea64b5683 -timeCreated: 1633451646 \ No newline at end of file diff --git a/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs b/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs deleted file mode 100644 index dce1864..0000000 --- a/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs +++ /dev/null @@ -1,289 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine; -using UnityEngine.TestTools; - -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class NetworkObjectMetricsTests : SingleClientMetricTestBase - { - // Keep less than 23 chars to avoid issues if compared against a 32-byte fixed string - // since it will have "(Clone)" appended - private const string k_NewNetworkObjectName = "MetricObject"; - private GameObject m_NewNetworkPrefab; - - /// - /// Use OnServerAndClientsCreated to create any additional prefabs that you might need - /// - protected override void OnServerAndClientsCreated() - { - base.OnServerAndClientsCreated(); - m_NewNetworkPrefab = CreateNetworkObjectPrefab(k_NewNetworkObjectName); - } - - private NetworkObject SpawnNetworkObject() - { - return SpawnObject(m_NewNetworkPrefab, m_ServerNetworkManager).GetComponent(); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectSpawnSentMetric() - { - var waitForMetricEvent = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent); - - var spawnedObject = SpawnNetworkObject(); - - yield return waitForMetricEvent.WaitForMetricsReceived(); - - var objectSpawnedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, objectSpawnedSentMetricValues.Count); - - var objectSpawned = objectSpawnedSentMetricValues.Last(); - Assert.AreEqual(Client.LocalClientId, objectSpawned.Connection.Id); - Assert.AreEqual(spawnedObject.name, objectSpawned.NetworkId.Name); - Assert.AreNotEqual(0, objectSpawned.BytesCount); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectSpawnReceivedMetric() - { - var waitForMetricEvent = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedReceived); - - var networkObject = SpawnNetworkObject(); - yield return s_DefaultWaitForTick; - - yield return waitForMetricEvent.WaitForMetricsReceived(); - - var objectSpawnedReceivedMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, objectSpawnedReceivedMetricValues.Count); - var clientSideObject = s_GlobalNetworkObjects[1][networkObject.NetworkObjectId]; - var objectSpawned = objectSpawnedReceivedMetricValues.First(); - Assert.AreEqual(Server.LocalClientId, objectSpawned.Connection.Id); - Assert.AreEqual(networkObject.NetworkObjectId, objectSpawned.NetworkId.NetworkId); - Assert.AreEqual(clientSideObject.name, objectSpawned.NetworkId.Name); - Assert.AreNotEqual(0, objectSpawned.BytesCount); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectDestroySentMetric() - { - var waitForMetricEvent = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent); - var networkObject = SpawnNetworkObject(); - var objectName = networkObject.name; - - Server.SpawnManager.OnDespawnObject(networkObject, true); - - // Wait for the metric to be received - yield return waitForMetricEvent.WaitForMetricsReceived(); - var objectDestroyedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - - // The server should have sent 1 destroy message to the 1 client connected - Assert.AreEqual(1, objectDestroyedSentMetricValues.Count); - - var objectDestroyed = objectDestroyedSentMetricValues.Last(); - Assert.AreEqual(Client.LocalClientId, objectDestroyed.Connection.Id); - Assert.AreEqual(objectName, objectDestroyed.NetworkId.Name); - Assert.AreNotEqual(0, objectDestroyed.BytesCount); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectDestroyReceivedMetric() - { - var networkObject = SpawnNetworkObject(); - - yield return s_DefaultWaitForTick; - - var waitForMetricEvent = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedReceived); - var objectId = networkObject.NetworkObjectId; - var objectName = s_GlobalNetworkObjects[1][objectId].name; - - Server.SpawnManager.OnDespawnObject(networkObject, true); - yield return s_DefaultWaitForTick; - - yield return waitForMetricEvent.WaitForMetricsReceived(); - - var objectDestroyedReceivedMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, objectDestroyedReceivedMetricValues.Count); - - var objectDestroyed = objectDestroyedReceivedMetricValues.First(); - Assert.AreEqual(Server.LocalClientId, objectDestroyed.Connection.Id); - Assert.AreEqual(objectId, objectDestroyed.NetworkId.NetworkId); - Assert.AreEqual(objectName, objectDestroyed.NetworkId.Name); - Assert.AreNotEqual(0, objectDestroyed.BytesCount); - } - - [UnityTest] - public IEnumerator TrackMultipleNetworkObjectSpawnSentMetric() - { - var networkObject1 = SpawnNetworkObject(); - var networkObject2 = SpawnNetworkObject(); - yield return s_DefaultWaitForTick; - - NetworkObject.NetworkHide(new List { networkObject1, networkObject2 }, Client.LocalClientId); - - yield return s_DefaultWaitForTick; - - var waitForMetricEvent = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectSpawnedSent); - - NetworkObject.NetworkShow(new List { networkObject1, networkObject2 }, Client.LocalClientId); - yield return s_DefaultWaitForTick; - - yield return waitForMetricEvent.WaitForMetricsReceived(); - - var objectSpawnedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, objectSpawnedSentMetricValues.Count); // As there's a client and server, this event is emitted twice. - Assert.That( - objectSpawnedSentMetricValues, - Has.Exactly(1).Matches( - x => Client.LocalClientId == x.Connection.Id - && x.NetworkId.NetworkId == networkObject1.NetworkObjectId - && x.NetworkId.Name == networkObject1.name)); - Assert.That( - objectSpawnedSentMetricValues, - Has.Exactly(1).Matches( - x => Client.LocalClientId == x.Connection.Id - && x.NetworkId.NetworkId == networkObject2.NetworkObjectId - && x.NetworkId.Name == networkObject2.name)); - - Assert.AreEqual(1, objectSpawnedSentMetricValues.Select(x => x.BytesCount).Distinct().Count()); - Assert.That(objectSpawnedSentMetricValues.Select(x => x.BytesCount), Has.All.Not.EqualTo(0)); - } - - [UnityTest] - public IEnumerator TrackMultipleNetworkObjectDestroySentMetric() - { - var networkObject1 = SpawnNetworkObject(); - var networkObject2 = SpawnNetworkObject(); - - yield return s_DefaultWaitForTick; - - var waitForMetricEvent = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.ObjectDestroyedSent); - - NetworkObject.NetworkHide(new List { networkObject1, networkObject2 }, Client.LocalClientId); - yield return s_DefaultWaitForTick; - yield return waitForMetricEvent.WaitForMetricsReceived(); - - var objectDestroyedSentMetricValues = waitForMetricEvent.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, objectDestroyedSentMetricValues.Count); // As there's a client and server, this event is emitted twice. - Assert.That( - objectDestroyedSentMetricValues, - Has.Exactly(1).Matches( - x => Client.LocalClientId == x.Connection.Id - && x.NetworkId.NetworkId == networkObject1.NetworkObjectId - && x.NetworkId.Name == networkObject1.name)); - Assert.That( - objectDestroyedSentMetricValues, - Has.Exactly(1).Matches( - x => Client.LocalClientId == x.Connection.Id - && x.NetworkId.NetworkId == networkObject2.NetworkObjectId - && x.NetworkId.Name == networkObject2.name)); - - Assert.AreEqual(1, objectDestroyedSentMetricValues.Select(x => x.BytesCount).Distinct().Count()); - Assert.That(objectDestroyedSentMetricValues.Select(x => x.BytesCount), Has.All.Not.EqualTo(0)); - } - -#if MULTIPLAYER_TOOLS_1_0_0_PRE_7 - [UnityTest] - public IEnumerator TrackNetworkObjectCountAfterSpawnOnServer() - { - SpawnNetworkObject(); - - var waitForGaugeValues = new WaitForGaugeMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects); - - yield return s_DefaultWaitForTick; - yield return waitForGaugeValues.WaitForMetricsReceived(); - - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(3, value); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectCountAfterSpawnOnClient() - { - SpawnNetworkObject(); - - //By default, we have 2 network objects - //There's a slight delay between the spawn on the server and the spawn on the client - //We want to have metrics when the value is different than the 2 default one to confirm the client has the new value - var waitForGaugeValues = new WaitForGaugeMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects, metric => (int)metric != 2); - - yield return waitForGaugeValues.WaitForMetricsReceived(); - - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(3, value); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectCountAfterDespawnOnServer() - { - var objectList = Server.SpawnManager.SpawnedObjectsList; - for (int i = objectList.Count - 1; i >= 0; --i) - { - objectList.ElementAt(i).Despawn(); - } - - var waitForGaugeValues = new WaitForGaugeMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects); - - yield return s_DefaultWaitForTick; - yield return waitForGaugeValues.WaitForMetricsReceived(); - - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(0, value); - } - - [UnityTest] - public IEnumerator TrackNetworkObjectCountAfterDespawnOnClient() - { - var initialSpawnCount = Server.SpawnManager.SpawnedObjectsList.Count; - var spawnedObjects = new List(); - //By default, we have 2 network objects and will have spawned 4 so we want to wait for metrics to tell us we have 6 spawned objects - var waitForGaugeValues = new WaitForGaugeMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects, metric => (int)metric == 6); - - for (int i = 0; i < 4; i++) - { - spawnedObjects.Add(SpawnObject(m_NewNetworkPrefab, Server)); - } - - yield return waitForGaugeValues.WaitForMetricsReceived(); - var value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(6, value); - - // Create a new gauge that waits for the initial spawned client count - waitForGaugeValues = new WaitForGaugeMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects, metric => (int)metric != 6); - - // Now despawn the 4 spawned objects - foreach (var spawnedObject in spawnedObjects) - { - spawnedObject.GetComponent().Despawn(); - } - spawnedObjects.Clear(); - yield return waitForGaugeValues.WaitForMetricsReceived(); - value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - - // Validate the value is equals to the spawned objects prior to spawning the network prefab instances - Assert.AreEqual(initialSpawnCount, value); - - // Create a new gauge that waits for the initial spawned client count - waitForGaugeValues = new WaitForGaugeMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkObjects, metric => (int)metric == 0); - - // Now assure despawning players are being tracked too - var spawnedPlayers = Server.SpawnManager.SpawnedObjectsList.ToList(); - foreach (var spawnedObject in spawnedPlayers) - { - spawnedObject.Despawn(); - } - yield return waitForGaugeValues.WaitForMetricsReceived(); - value = waitForGaugeValues.AssertMetricValueHaveBeenFound(); - // Nothing should be spawned on the client at this point - Assert.AreEqual(0, value); - } -#endif - } -} -#endif diff --git a/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs.meta b/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs.meta deleted file mode 100644 index d09dcac..0000000 --- a/Tests/Runtime/Metrics/NetworkObjectMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c4cb56c442bed164da4908e54590dfeb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs b/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs deleted file mode 100644 index 640cee4..0000000 --- a/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class NetworkVariableMetricsTests : SingleClientMetricTestBase - { - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - base.OnCreatePlayerPrefab(); - } - - [UnityTest] - public IEnumerator TrackNetworkVariableDeltaSentMetric() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaSent); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var metricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - - bool found = false; - foreach (var networkVariableDeltaSent in metricValues) - { - if (nameof(NetworkVariableComponent.MyNetworkVariable) == networkVariableDeltaSent.Name && - Client.LocalClientId == networkVariableDeltaSent.Connection.Id && - 0 != networkVariableDeltaSent.BytesCount) - { - found = true; - } - } - Assert.IsTrue(found); - } - - [UnityTest] - public IEnumerator TrackNetworkVariableDeltaReceivedMetric() - { - var waitForMetricValues = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.NetworkVariableDeltaReceived); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var metricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, metricValues.Count); // We have an instance each of the player prefabs - - var first = metricValues.First(); - Assert.AreEqual(nameof(NetworkVariableComponent.MyNetworkVariable), first.Name); - Assert.AreNotEqual(0, first.BytesCount); - - var last = metricValues.Last(); - Assert.AreEqual(nameof(NetworkVariableComponent.MyNetworkVariable), last.Name); - Assert.AreNotEqual(0, last.BytesCount); - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs.meta b/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs.meta deleted file mode 100644 index 690106b..0000000 --- a/Tests/Runtime/Metrics/NetworkVariableMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: abbea688505c90d4f82bfa5ea3ee1cd9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs b/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs deleted file mode 100644 index a3fcf30..0000000 --- a/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs +++ /dev/null @@ -1,113 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class OwnershipChangeMetricsTests : SingleClientMetricTestBase - { - private const string k_NewNetworkObjectName = "TestNetworkObjectToSpawn"; - private NetworkObject m_NewNetworkPrefab; - // Header is dynamically sized due to packing, will be 2 bytes for all test messages. - private const int k_MessageHeaderSize = 2; - - protected override void OnServerAndClientsCreated() - { - var gameObject = new GameObject(k_NewNetworkObjectName); - m_NewNetworkPrefab = gameObject.AddComponent(); - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(m_NewNetworkPrefab); - - var networkPrefab = new NetworkPrefab { Prefab = gameObject }; - m_ServerNetworkManager.NetworkConfig.Prefabs.Add(networkPrefab); - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.Prefabs.Add(networkPrefab); - } - base.OnServerAndClientsCreated(); - } - - private NetworkObject SpawnNetworkObject() - { - // Spawn another network object so we can hide multiple. - var gameObject = Object.Instantiate(m_NewNetworkPrefab); // new GameObject(NewNetworkObjectName); - var networkObject = gameObject.GetComponent(); - networkObject.NetworkManagerOwner = Server; - networkObject.Spawn(); - - return networkObject; - } - - private int GetWriteSizeForOwnerChange(NetworkObject networkObject, ulong newOwner) - { - var message = new ChangeOwnershipMessage - { - NetworkObjectId = networkObject.NetworkObjectId, - OwnerClientId = newOwner - }; - using var writer = new FastBufferWriter(1024, Allocator.Temp); - message.Serialize(writer, message.Version); - return writer.Length; - } - - [UnityTest] - public IEnumerator TrackOwnershipChangeSentMetric() - { - var networkObject = SpawnNetworkObject(); - - yield return new WaitForSeconds(0.2f); - - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeSent); - - networkObject.ChangeOwnership(1); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var metricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - - var ownershipChangeSent = metricValues.First(); - Assert.AreEqual(networkObject.NetworkObjectId, ownershipChangeSent.NetworkId.NetworkId); - Assert.AreEqual(Server.LocalClientId, ownershipChangeSent.Connection.Id); - Assert.AreEqual(0, ownershipChangeSent.BytesCount); - - // The first metric is to the server(self), so its size is now correctly reported as 0. - // Let's check the last one instead, to have a valid value - ownershipChangeSent = metricValues.Last(); - Assert.AreEqual(networkObject.NetworkObjectId, ownershipChangeSent.NetworkId.NetworkId); - Assert.AreEqual(Client.LocalClientId, ownershipChangeSent.Connection.Id); - - var serializedLength = GetWriteSizeForOwnerChange(networkObject, 1); - Assert.AreEqual(serializedLength + k_MessageHeaderSize, ownershipChangeSent.BytesCount); - } - - [UnityTest] - public IEnumerator TrackOwnershipChangeReceivedMetric() - { - var networkObject = SpawnNetworkObject(); - - yield return new WaitForSeconds(0.2f); - - var waitForMetricValues = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.OwnershipChangeReceived); - - networkObject.ChangeOwnership(1); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var metricValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, metricValues.Count); - - var ownershipChangeReceived = metricValues.First(); - Assert.AreEqual(networkObject.NetworkObjectId, ownershipChangeReceived.NetworkId.NetworkId); - - var serializedLength = GetWriteSizeForOwnerChange(networkObject, 1); - Assert.AreEqual(serializedLength, ownershipChangeReceived.BytesCount); - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs.meta b/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs.meta deleted file mode 100644 index a227871..0000000 --- a/Tests/Runtime/Metrics/OwnershipChangeMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 86daf1dbe91c9ad40818743a805d0052 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/PacketLossMetricsTests.cs b/Tests/Runtime/Metrics/PacketLossMetricsTests.cs deleted file mode 100644 index 91c242b..0000000 --- a/Tests/Runtime/Metrics/PacketLossMetricsTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -#if MULTIPLAYER_TOOLS -#if MULTIPLAYER_TOOLS_1_0_0_PRE_7 - -using System.Collections; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.TestHelpers.Runtime.Metrics; -using Unity.Netcode.Transports.UTP; -#if UTP_TRANSPORT_2_0_ABOVE -using Unity.Networking.Transport.Utilities; -#endif -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class PacketLossMetricsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - private readonly int m_PacketLossRate = 25; - private readonly int m_PacketLossRangeDelta = 3; - private readonly int m_MessageSize = 200; - - public PacketLossMetricsTests() - : base(HostOrServer.Server) - { } - - protected override void OnServerAndClientsCreated() - { - var clientTransport = (UnityTransport)m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport; -#if !UTP_TRANSPORT_2_0_ABOVE - clientTransport.SetDebugSimulatorParameters(0, 0, m_PacketLossRate); -#endif - - // Determined through trial and error. With both UTP 1.2 and 2.0, this random seed - // results in an effective packet loss percentage between 22% and 28%. Future UTP - // updates may change the RNG call patterns and cause this test to fail, in which - // case the value should be modified again. - clientTransport.DebugSimulatorRandomSeed = 4; - - base.OnServerAndClientsCreated(); - } - - [UnityTest] - public IEnumerator TrackPacketLossAsServer() - { - var waitForPacketLossMetric = new WaitForGaugeMetricValues((m_ServerNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, - NetworkMetricTypes.PacketLoss, - metric => metric == 0.0d); - - for (int i = 0; i < 1000; ++i) - { - using var writer = new FastBufferWriter(m_MessageSize, Allocator.Persistent); - writer.WriteBytesSafe(new byte[m_MessageSize]); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage("Test", m_ServerNetworkManager.ConnectedClientsIds, writer); - } - - yield return waitForPacketLossMetric.WaitForMetricsReceived(); - - var packetLossValue = waitForPacketLossMetric.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(0d, packetLossValue); - } - - [UnityTest] - public IEnumerator TrackPacketLossAsClient() - { - double packetLossRateMinRange = (m_PacketLossRate - m_PacketLossRangeDelta) / 100d; - double packetLossRateMaxrange = (m_PacketLossRate + m_PacketLossRangeDelta) / 100d; - var clientNetworkManager = m_ClientNetworkManagers[0]; - -#if UTP_TRANSPORT_2_0_ABOVE - var clientTransport = (UnityTransport)clientNetworkManager.NetworkConfig.NetworkTransport; - clientTransport.NetworkDriver.CurrentSettings.TryGet(out var parameters); - parameters.PacketDropPercentage = m_PacketLossRate; - clientTransport.NetworkDriver.ModifySimulatorStageParameters(parameters); -#endif - - var waitForPacketLossMetric = new WaitForGaugeMetricValues((clientNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, - NetworkMetricTypes.PacketLoss, - metric => packetLossRateMinRange <= metric && metric <= packetLossRateMaxrange); - - for (int i = 0; i < 1000; ++i) - { - using var writer = new FastBufferWriter(m_MessageSize, Allocator.Persistent); - writer.WriteBytesSafe(new byte[m_MessageSize]); - m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage("Test", m_ServerNetworkManager.ConnectedClientsIds, writer); - } - - yield return waitForPacketLossMetric.WaitForMetricsReceived(); - - var packetLossValue = waitForPacketLossMetric.AssertMetricValueHaveBeenFound(); - Assert.That(packetLossValue, Is.InRange(packetLossRateMinRange, packetLossRateMaxrange)); - } - } -} - -#endif -#endif diff --git a/Tests/Runtime/Metrics/PacketLossMetricsTests.cs.meta b/Tests/Runtime/Metrics/PacketLossMetricsTests.cs.meta deleted file mode 100644 index d48f305..0000000 --- a/Tests/Runtime/Metrics/PacketLossMetricsTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 12e64da4670d49a4a89da38d18e64396 -timeCreated: 1648133968 \ No newline at end of file diff --git a/Tests/Runtime/Metrics/PacketMetricsTests.cs b/Tests/Runtime/Metrics/PacketMetricsTests.cs deleted file mode 100644 index 90707de..0000000 --- a/Tests/Runtime/Metrics/PacketMetricsTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -#if MULTIPLAYER_TOOLS -#if MULTIPLAYER_TOOLS_1_0_0_PRE_7 -using System.Collections; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class PacketMetricsTests : SingleClientMetricTestBase - { - [UnityTest] - public IEnumerator TrackPacketSentMetric() - { - var waitForMetricValues = new WaitForCounterMetricValue(ServerMetrics.Dispatcher, NetworkMetricTypes.PacketsSent, metric => metric > 0); - - using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp)) - { - writer.WriteValueSafe(1337); - Server.CustomMessagingManager.SendUnnamedMessageToAll(writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var totalPacketCount = waitForMetricValues.AssertMetricValueHaveBeenFound(); - Assert.That(totalPacketCount, Is.InRange(1, 4)); - } - - [UnityTest] - public IEnumerator TrackPacketReceivedMetric() - { - var waitForMetricValues = new WaitForCounterMetricValue(ClientMetrics.Dispatcher, NetworkMetricTypes.PacketsReceived, metric => metric > 0); - - using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp)) - { - writer.WriteValueSafe(1337); - Server.CustomMessagingManager.SendUnnamedMessageToAll(writer); - } - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var totalPacketCount = waitForMetricValues.AssertMetricValueHaveBeenFound(); - Assert.That(totalPacketCount, Is.InRange(1, 4)); - } - } -} -#endif -#endif diff --git a/Tests/Runtime/Metrics/PacketMetricsTests.cs.meta b/Tests/Runtime/Metrics/PacketMetricsTests.cs.meta deleted file mode 100644 index d55ef2f..0000000 --- a/Tests/Runtime/Metrics/PacketMetricsTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 84a4884f4ea744a9944284d56b29531b -timeCreated: 1644269306 \ No newline at end of file diff --git a/Tests/Runtime/Metrics/RpcMetricsTests.cs b/Tests/Runtime/Metrics/RpcMetricsTests.cs deleted file mode 100644 index b2b186a..0000000 --- a/Tests/Runtime/Metrics/RpcMetricsTests.cs +++ /dev/null @@ -1,145 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class RpcMetricsTests : DualClientMetricTestBase - { - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - base.OnCreatePlayerPrefab(); - } - - [UnityTest] - public IEnumerator TrackRpcSentMetricOnServerToOnlyOneClientWithArray() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(new ClientRpcParams - { - Send = new ClientRpcSendParams - { - TargetClientIds = new[] { FirstClient.LocalClientId } - } - }); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, serverRpcSentValues.Count); - - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); - Assert.AreEqual(FirstClient.LocalClientId, serverRpcSentValues.First().Connection.Id); - } - - [UnityTest] - public IEnumerator TrackRpcSentMetricOnServerToOnlyOneClientWithNativeArray() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(new ClientRpcParams - { - Send = new ClientRpcSendParams - { - TargetClientIdsNativeArray = new NativeArray(new[] { FirstClient.LocalClientId }, Allocator.Temp) - } - }); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, serverRpcSentValues.Count); - - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); - Assert.AreEqual(FirstClient.LocalClientId, serverRpcSentValues.First().Connection.Id); - } - - [UnityTest] - public IEnumerator TrackRpcSentMetricOnServerToAllClients() - { - var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(); - - yield return waitForMetricValues.WaitForMetricsReceived(); - - var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(3, serverRpcSentValues.Count); // Server will receive this, since it's host - - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); - Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); - Assert.Contains(Server.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); - Assert.Contains(FirstClient.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); - Assert.Contains(SecondClient.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); - } - - [UnityTest] - public IEnumerator TrackRpcSentMetricOnClient() - { - var waitForClientMetricsValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - - m_PlayerNetworkObjects[FirstClient.LocalClientId][FirstClient.LocalClientId].GetComponent().MyServerRpc(); - - yield return waitForClientMetricsValues.WaitForMetricsReceived(); - - var clientRpcSentValues = waitForClientMetricsValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, clientRpcSentValues.Count); - - var rpcSent = clientRpcSentValues.First(); - Assert.AreEqual(Server.LocalClientId, rpcSent.Connection.Id); - Assert.AreEqual(nameof(RpcTestComponent.MyServerRpc), rpcSent.Name); - Assert.AreEqual(nameof(RpcTestComponent), rpcSent.NetworkBehaviourName); - Assert.AreNotEqual(0, rpcSent.BytesCount); - } - - [UnityTest] - public IEnumerator TrackRpcReceivedMetricOnServer() - { - var waitForServerMetricsValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcReceived); - m_PlayerNetworkObjects[FirstClient.LocalClientId][FirstClient.LocalClientId].GetComponent().MyServerRpc(); - - yield return waitForServerMetricsValues.WaitForMetricsReceived(); - - var serverRpcReceivedValues = waitForServerMetricsValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, serverRpcReceivedValues.Count); - - var rpcReceived = serverRpcReceivedValues.First(); - Assert.AreEqual(FirstClient.LocalClientId, rpcReceived.Connection.Id); - Assert.AreEqual(nameof(RpcTestComponent.MyServerRpc), rpcReceived.Name); - Assert.AreEqual(nameof(RpcTestComponent), rpcReceived.NetworkBehaviourName); - Assert.AreNotEqual(0, rpcReceived.BytesCount); - } - - [UnityTest] - public IEnumerator TrackRpcReceivedMetricOnClient() - { - var waitForClientMetricsValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.RpcReceived); - - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(); - - yield return waitForClientMetricsValues.WaitForMetricsReceived(); - - var clientRpcReceivedValues = waitForClientMetricsValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, clientRpcReceivedValues.Count); - - var rpcReceived = clientRpcReceivedValues.First(); - Assert.AreEqual(Server.LocalClientId, rpcReceived.Connection.Id); - Assert.AreEqual(nameof(RpcTestComponent.MyClientRpc), rpcReceived.Name); - Assert.AreEqual(nameof(RpcTestComponent), rpcReceived.NetworkBehaviourName); - Assert.AreNotEqual(0, rpcReceived.BytesCount); - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/RpcMetricsTests.cs.meta b/Tests/Runtime/Metrics/RpcMetricsTests.cs.meta deleted file mode 100644 index 38427d5..0000000 --- a/Tests/Runtime/Metrics/RpcMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 02a31cf8be00f8b46b65477d648b297d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/RttMetricsTests.cs b/Tests/Runtime/Metrics/RttMetricsTests.cs deleted file mode 100644 index 2c77c66..0000000 --- a/Tests/Runtime/Metrics/RttMetricsTests.cs +++ /dev/null @@ -1,88 +0,0 @@ -#if MULTIPLAYER_TOOLS -#if MULTIPLAYER_TOOLS_1_0_0_PRE_7 - -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - /// - /// Note: This is one way to easily identify each specific test. - /// Since the test only tested 1 and then 2 clients, I made this - /// and enum, but you can always remove the enum in the constructor, - /// replace it with an int, and then test from 1 to 9 clients. - /// Just an example of how you can accomplish the same task using - /// the NetcodeIntegrationTest - /// - [TestFixture(ClientCount.OneClient)] - [TestFixture(ClientCount.TwoClients)] - internal class RttMetricsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => m_ClientCount; - - public enum ClientCount - { - OneClient, - TwoClients - } - - private int m_ClientCount; - - public RttMetricsTests(ClientCount numberOfClients) - { - m_ClientCount = numberOfClients == ClientCount.OneClient ? 1 : 2; - } - - [UnityTest] - public IEnumerator TrackRttMetricServerToClient() - { - var waitForMetricValues = new WaitForGaugeMetricValues((m_ServerNetworkManager.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.RttToServer); - - using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp)) - { - writer.WriteValueSafe(1337); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer); - } - - yield return WaitForConditionOrTimeOut(() => waitForMetricValues.MetricFound()); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"{nameof(TrackRttMetricServerToClient)} timed out waiting for metric to be found for {m_ClientCount} clients!"); - - var rttValue = waitForMetricValues.AssertMetricValueHaveBeenFound(); - Assert.AreEqual(0f, rttValue); - } - - [UnityTest] - public IEnumerator TrackRttMetricClientToServer() - { - var clientGaugeMetricValues = new List(); - foreach (var client in m_ClientNetworkManagers) - { - clientGaugeMetricValues.Add(new WaitForGaugeMetricValues((client.NetworkMetrics as NetworkMetrics).Dispatcher, NetworkMetricTypes.RttToServer, metric => metric > 0f)); - } - - using (var writer = new FastBufferWriter(sizeof(uint), Allocator.Temp)) - { - writer.WriteValueSafe(1337); - m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer); - } - - yield return WaitForConditionOrTimeOut(() => clientGaugeMetricValues.Where((c) => c.MetricFound()).Count() == NumberOfClients); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"{nameof(TrackRttMetricClientToServer)} timed out waiting for metric to be found for {m_ClientCount} clients!"); - - foreach (var clientGaugeMetricValue in clientGaugeMetricValues) - { - var rttValue = clientGaugeMetricValue.AssertMetricValueHaveBeenFound(); - Assert.That(rttValue, Is.GreaterThanOrEqualTo(1e-3f)); - } - } - } -} -#endif -#endif diff --git a/Tests/Runtime/Metrics/RttMetricsTests.cs.meta b/Tests/Runtime/Metrics/RttMetricsTests.cs.meta deleted file mode 100644 index 704d1b4..0000000 --- a/Tests/Runtime/Metrics/RttMetricsTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 452fbcb436d24291ba7db3a68e3e50ac -timeCreated: 1644269321 \ No newline at end of file diff --git a/Tests/Runtime/Metrics/ServerLogsMetricTests.cs b/Tests/Runtime/Metrics/ServerLogsMetricTests.cs deleted file mode 100644 index 4fbd75f..0000000 --- a/Tests/Runtime/Metrics/ServerLogsMetricTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System; -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime.Metrics; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class ServerLogsMetricTests : SingleClientMetricTestBase - { - // Header is dynamically sized due to packing, will be 3 bytes for all test messages. - private const int k_MessageHeaderSize = 3; - - protected override IEnumerator OnSetup() - { - m_CreateServerFirst = false; - return base.OnSetup(); - } - - - private int GetWriteSizeForLog(NetworkLog.LogType logType, string logMessage) - { - var message = new ServerLogMessage - { - LogType = logType, - Message = logMessage - }; - using var writer = new FastBufferWriter(1024, Allocator.Temp); - message.Serialize(writer, message.Version); - return writer.Length; - } - - [UnityTest] - public IEnumerator TrackServerLogSentMetric() - { - // Set the client NetworkManager to assure the log is sent - NetworkLog.NetworkManagerOverride = Client; - var waitForSentMetric = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.ServerLogSent); - - var message = Guid.NewGuid().ToString(); - Client.LogLevel = LogLevel.Developer; - Server.LogLevel = LogLevel.Developer; - NetworkLog.LogWarningServer(message); - yield return s_DefaultWaitForTick; - - yield return waitForSentMetric.WaitForMetricsReceived(); - - var sentMetrics = waitForSentMetric.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, sentMetrics.Count); - - var sentMetric = sentMetrics.First(); - Assert.AreEqual(Server.LocalClientId, sentMetric.Connection.Id); - Assert.AreEqual((uint)NetworkLog.LogType.Warning, (uint)sentMetric.LogLevel); - - var serializedLength = GetWriteSizeForLog(NetworkLog.LogType.Warning, message); - Assert.AreEqual(serializedLength + k_MessageHeaderSize, sentMetric.BytesCount); - } - - [UnityTest] - public IEnumerator TrackServerLogReceivedMetric() - { - var waitForReceivedMetric = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.ServerLogReceived); - - var message = Guid.NewGuid().ToString(); - Client.LogLevel = LogLevel.Developer; - Server.LogLevel = LogLevel.Developer; - NetworkLog.LogWarningServer(message); - - yield return s_DefaultWaitForTick; - - yield return waitForReceivedMetric.WaitForMetricsReceived(); - - var receivedMetrics = waitForReceivedMetric.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(1, receivedMetrics.Count); - - var receivedMetric = receivedMetrics.First(); - Assert.AreEqual(Client.LocalClientId, receivedMetric.Connection.Id); - Assert.AreEqual((uint)NetworkLog.LogType.Warning, (uint)receivedMetric.LogLevel); - - var serializedLength = GetWriteSizeForLog(NetworkLog.LogType.Warning, message); - Assert.AreEqual(serializedLength, receivedMetric.BytesCount); - } - - protected override IEnumerator OnTearDown() - { - NetworkLog.NetworkManagerOverride = null; - return base.OnTearDown(); - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/ServerLogsMetricTests.cs.meta b/Tests/Runtime/Metrics/ServerLogsMetricTests.cs.meta deleted file mode 100644 index 8eccb56..0000000 --- a/Tests/Runtime/Metrics/ServerLogsMetricTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5ba082aac78de5d488f621a0cbaf16a6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs b/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs deleted file mode 100644 index 94e67e5..0000000 --- a/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -#if MULTIPLAYER_TOOLS -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Collections; -using Unity.Multiplayer.Tools.MetricTypes; -using Unity.Multiplayer.Tools.NetStats; -using Unity.Netcode.TestHelpers.Runtime.Metrics; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests.Metrics -{ - internal class TransportBytesMetricsTests : SingleClientMetricTestBase - { - // Header is dynamically sized due to packing, will be 2 bytes for all test messages. - private const int k_MessageHeaderSize = 2; - private static readonly long k_MessageOverhead = 8 + FastBufferWriter.GetWriteSize() + k_MessageHeaderSize; - - [UnityTest] - public IEnumerator TrackTotalNumberOfBytesSent() - { - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - var observer = new TotalBytesObserver(ClientMetrics.Dispatcher, NetworkMetricTypes.TotalBytesReceived); - try - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Client.LocalClientId, writer); - } - finally - { - writer.Dispose(); - } - - var nbFrames = 0; - while (!observer.Found || nbFrames < 10) - { - yield return null; - nbFrames++; - } - - Assert.True(observer.Found); - Assert.AreEqual(((FastBufferWriter.GetWriteSize(messageName) + k_MessageOverhead) + 7) & ~7, observer.Value); - } - - [UnityTest] - public IEnumerator TrackTotalNumberOfBytesReceived() - { - var messageName = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); - var writer = new FastBufferWriter(1300, Allocator.Temp); - var observer = new TotalBytesObserver(ClientMetrics.Dispatcher, NetworkMetricTypes.TotalBytesReceived); - try - { - writer.WriteValueSafe(messageName); - - Server.CustomMessagingManager.SendNamedMessage(messageName.Value.ToString(), Client.LocalClientId, writer); - } - finally - { - writer.Dispose(); - } - - var nbFrames = 0; - while (!observer.Found || nbFrames < 10) - { - yield return null; - nbFrames++; - } - - Assert.True(observer.Found); - Assert.AreEqual(((FastBufferWriter.GetWriteSize(messageName) + k_MessageOverhead) + 7) & ~7, observer.Value); - } - - private class TotalBytesObserver : IMetricObserver - { - private readonly DirectionalMetricInfo m_MetricInfo; - - public TotalBytesObserver(IMetricDispatcher dispatcher, DirectionalMetricInfo metricInfo) - { - m_MetricInfo = metricInfo; - - dispatcher.RegisterObserver(this); - } - - public bool Found { get; private set; } - - public long Value { get; private set; } - - private int m_BytesFoundCounter; - private long m_TotalBytes; - - public void Observe(MetricCollection collection) - { - if (collection.TryGetCounter(m_MetricInfo.Id, out var counter) && counter.Value > 0) - { - // Don't assign another observed value once one is already observed - if (!Found) - { - Found = true; - Value = counter.Value; - m_TotalBytes += ((counter.Value + 7) & ~7); - m_BytesFoundCounter++; - UnityEngine.Debug.Log($"[{m_BytesFoundCounter}] Bytes Observed {counter.Value} | Total Bytes Observed: {m_TotalBytes}"); - } - } - } - } - } -} -#endif diff --git a/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs.meta b/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs.meta deleted file mode 100644 index 2cfb1f3..0000000 --- a/Tests/Runtime/Metrics/TransportBytesMetricsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a8be98b50d230114f853054c479341ee -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NestedNetworkManagerTests.cs b/Tests/Runtime/NestedNetworkManagerTests.cs deleted file mode 100644 index c31f8a8..0000000 --- a/Tests/Runtime/NestedNetworkManagerTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NestedNetworkManagerTests - { - [Test] - public void CheckNestedNetworkManager() - { - var parent = new GameObject("ParentObject"); - var networkManagerObject = new GameObject(nameof(CheckNestedNetworkManager)); - - var unityTransport = networkManagerObject.AddComponent(); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig() { NetworkTransport = unityTransport }; - - // Make our NetworkManager's GameObject nested - networkManagerObject.transform.parent = parent.transform; - - // Generate the error message we are expecting to see - var messageToCheck = NetworkManager.GenerateNestedNetworkManagerMessage(networkManagerObject.transform); - - // Trap for the nested NetworkManager exception -#if UNITY_EDITOR - LogAssert.Expect(LogType.Error, messageToCheck); -#else - LogAssert.Expect(LogType.Exception, $"Exception: {messageToCheck}"); -#endif - - // Clean up - Object.Destroy(parent); - } - } -} diff --git a/Tests/Runtime/NestedNetworkManagerTests.cs.meta b/Tests/Runtime/NestedNetworkManagerTests.cs.meta deleted file mode 100644 index 0cff7a3..0000000 --- a/Tests/Runtime/NestedNetworkManagerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 738f6d8fc9319fe42a986c2f43989642 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkBehaviourGenericTests.cs b/Tests/Runtime/NetworkBehaviourGenericTests.cs deleted file mode 100644 index 91e3124..0000000 --- a/Tests/Runtime/NetworkBehaviourGenericTests.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// This class is for testing general fixes or functionality of NetworkBehaviours - /// - internal class NetworkBehaviourGenericTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 0; - - private bool m_AllowServerToStart; - - protected override bool CanStartServerAndClients() - { - return m_AllowServerToStart; - } - - internal class SimpleNetworkBehaviour : NetworkBehaviour - { - public bool OnNetworkDespawnCalled; - - public override void OnNetworkDespawn() - { - OnNetworkDespawnCalled = true; - base.OnNetworkDespawn(); - } - } - - protected override IEnumerator OnSetup() - { - m_AllowServerToStart = false; - return base.OnSetup(); - } - - /// - /// This validates the fix for when a child GameObject with a NetworkBehaviour - /// is deleted while the parent GameObject with a NetworkObject is spawned and - /// is not deleted until a later time would cause an exception due to the - /// NetworkBehaviour not being removed from the NetworkObject.ChildNetworkBehaviours - /// list. - /// - [UnityTest] - public IEnumerator ValidatedDisableddNetworkBehaviourWarning() - { - m_AllowServerToStart = true; - - yield return s_DefaultWaitForTick; - - // Now just start the Host - yield return StartServerAndClients(); - - var parentObject = new GameObject(); - var childObject = new GameObject - { - name = "ChildObject" - }; - childObject.transform.parent = parentObject.transform; - var parentNetworkObject = parentObject.AddComponent(); - var childBehaviour = childObject.AddComponent(); - - // Set the child object to be inactive in the hierarchy - childObject.SetActive(false); - - LogAssert.Expect(LogType.Warning, $"{childObject.name} is disabled! Netcode for GameObjects does not support spawning disabled NetworkBehaviours! The {childBehaviour.GetType().Name} component was skipped during spawn!"); - - parentNetworkObject.Spawn(); - yield return s_DefaultWaitForTick; - } - - /// - /// This test validates a fix to NetworkBehaviour.NetworkObject when - /// the NetworkManager.LogLevel is set to Developer - /// Note: This test does not require any clients, but should not impact this - /// particular test if new tests are added to this class that do require clients - /// - [UnityTest] - public IEnumerator ValidateNoSpam() - { - m_AllowServerToStart = true; - var objectToTest = new GameObject(); - var simpleNetworkBehaviour = objectToTest.AddComponent(); - - // Now just start the Host - yield return StartServerAndClients(); - - // set the log level to developer - m_ServerNetworkManager.LogLevel = LogLevel.Developer; - - // The only valid condition for this would be if the NetworkBehaviour is spawned. - simpleNetworkBehaviour.IsSpawned = true; - - // Verify the warning gets logged under normal conditions - var isNull = simpleNetworkBehaviour.NetworkObject == null; - LogAssert.Expect(LogType.Warning, $"[Netcode] Could not get {nameof(NetworkObject)} for the {nameof(NetworkBehaviour)}. Are you missing a {nameof(NetworkObject)} component?"); - - var networkObjectToTest = objectToTest.AddComponent(); - networkObjectToTest.NetworkManagerOwner = m_ServerNetworkManager; - networkObjectToTest.Spawn(); - - // Assure no log messages are logged when they should not be logged - isNull = simpleNetworkBehaviour.NetworkObject != null; - LogAssert.NoUnexpectedReceived(); - - networkObjectToTest.Despawn(); - Object.Destroy(networkObjectToTest); - } - - /// - /// This validates the fix for when a child GameObject with a NetworkBehaviour - /// is deleted while the parent GameObject with a NetworkObject is spawned and - /// is not deleted until a later time would cause an exception due to the - /// NetworkBehaviour not being removed from the NetworkObject.ChildNetworkBehaviours - /// list. - /// - [UnityTest] - public IEnumerator ValidateDeleteChildNetworkBehaviour() - { - m_AllowServerToStart = true; - - yield return s_DefaultWaitForTick; - - // Now just start the Host - yield return StartServerAndClients(); - - var parentObject = new GameObject(); - var childObject = new GameObject(); - childObject.transform.parent = parentObject.transform; - var parentNetworkObject = parentObject.AddComponent(); - childObject.AddComponent(); - - parentNetworkObject.Spawn(); - yield return s_DefaultWaitForTick; - - // Destroy the child object with child NetworkBehaviour - Object.Destroy(childObject); - - yield return s_DefaultWaitForTick; - - // Assure no log messages are logged when they should not be logged - LogAssert.NoUnexpectedReceived(); - - // Destroy the parent object which should not cause any exceptions - // (validating the fix) - Object.Destroy(parentObject); - } - - protected override void OnPlayerPrefabGameObjectCreated() - { - // Adds the SimpleNetworkBehaviour before the NetworkObject - // for OnNetworkDespawnInvokedWhenClientDisconnects testing - m_PlayerPrefab.AddComponent(); - } - - /// - /// This validates that upon a client disconnecting, the server-side - /// client's player clone will invoke NetworkBehaviour.OnNetworkDespawn - /// when the component precedes the NetworkObject component.(PR-2323) - /// - [UnityTest] - public IEnumerator OnNetworkDespawnInvokedWhenClientDisconnects() - { - m_AllowServerToStart = true; - - // Now just start the Host - yield return StartServerAndClients(); - - // Now create and connect a new client - yield return CreateAndStartNewClient(); - - var serverSidePlayer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - yield return StopOneClient(m_ClientNetworkManagers[0]); - - Assert.True(serverSidePlayer.OnNetworkDespawnCalled, $"Server-side player clone did not invoke OnNetworkDespawn!"); - } - } -} diff --git a/Tests/Runtime/NetworkBehaviourGenericTests.cs.meta b/Tests/Runtime/NetworkBehaviourGenericTests.cs.meta deleted file mode 100644 index 38444d1..0000000 --- a/Tests/Runtime/NetworkBehaviourGenericTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f87989d8d290ed24a9048b6dbddae527 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs b/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs deleted file mode 100644 index 00d3c08..0000000 --- a/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.DAHost)] - internal class NetworkBehaviourPrePostSpawnTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 0; - - private bool m_AllowServerToStart; - - private GameObject m_PrePostSpawnObject; - - public NetworkBehaviourPrePostSpawnTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override void OnServerAndClientsCreated() - { - m_PrePostSpawnObject = CreateNetworkObjectPrefab("PrePostSpawn"); - // Reverse the order of the components to get inverted spawn sequence - m_PrePostSpawnObject.AddComponent(); - m_PrePostSpawnObject.AddComponent(); - base.OnServerAndClientsCreated(); - } - - internal class NetworkBehaviourPreSpawn : NetworkBehaviour - { - public static int ValueToSet; - public bool OnNetworkPreSpawnCalled; - public bool NetworkVarValueMatches; - - public NetworkVariable TestNetworkVariable; - - protected override void OnNetworkPreSpawn(ref NetworkManager networkManager) - { - OnNetworkPreSpawnCalled = true; - // If we are the server, then set the randomly generated value (1-200). - // Otherwise, just set the value to 0. - // TODO: Make adjustments when integrated CMB service testing is added - var val = networkManager.IsServer ? ValueToSet : 0; - // Instantiate the NetworkVariable as everyone read & owner write while also setting the value - TestNetworkVariable = new NetworkVariable(val, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - base.OnNetworkPreSpawn(ref networkManager); - } - - public override void OnNetworkSpawn() - { - // For both client and server this should match at this point - NetworkVarValueMatches = TestNetworkVariable.Value == ValueToSet; - base.OnNetworkSpawn(); - } - } - - internal class NetworkBehaviourPostSpawn : NetworkBehaviour - { - public bool OnNetworkPostSpawnCalled; - - private NetworkBehaviourPreSpawn m_NetworkBehaviourPreSpawn; - - public int ValueSet; - - public override void OnNetworkSpawn() - { - // Obtain the NetworkBehaviourPreSpawn component - // (could also do this during OnNetworkPreSpawn if we wanted) - m_NetworkBehaviourPreSpawn = GetComponent(); - base.OnNetworkSpawn(); - } - - protected override void OnNetworkPostSpawn() - { - OnNetworkPostSpawnCalled = true; - // We should be able to access the component we got during OnNetworkSpawn and all values should be set - // (i.e. OnNetworkSpawn run on all NetworkObject relative NetworkBehaviours) - ValueSet = m_NetworkBehaviourPreSpawn.TestNetworkVariable.Value; - base.OnNetworkPostSpawn(); - } - - } - - protected override bool CanStartServerAndClients() - { - return m_AllowServerToStart; - } - - protected override IEnumerator OnSetup() - { - m_AllowServerToStart = false; - return base.OnSetup(); - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs; - base.OnNewClientCreated(networkManager); - } - - /// - /// This validates that pre spawn can be used to instantiate and assign a NetworkVariable (or other prespawn tasks) - /// which can be useful for assigning a NetworkVariable value on the server side when the NetworkVariable has owner write permissions. - /// This also assures that duruing post spawn all associated NetworkBehaviours have run through the OnNetworkSpawn pass (i.e. OnNetworkSpawn order is not an issue) - /// - [UnityTest] - public IEnumerator OnNetworkPreAndPostSpawn() - { - m_AllowServerToStart = true; - NetworkBehaviourPreSpawn.ValueToSet = Random.Range(1, 200); - yield return StartServerAndClients(); - - yield return CreateAndStartNewClient(); - - // Spawn the object with the newly joined client as the owner - var networkManager = m_DistributedAuthority ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - var authorityInstance = SpawnObject(m_PrePostSpawnObject, networkManager); - var authorityNetworkObject = authorityInstance.GetComponent(); - var authorityPreSpawn = authorityInstance.GetComponent(); - var authorityPostSpawn = authorityInstance.GetComponent(); - - yield return WaitForConditionOrTimeOut(() => s_GlobalNetworkObjects.ContainsKey(m_ClientNetworkManagers[0].LocalClientId) - && s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId].ContainsKey(authorityNetworkObject.NetworkObjectId)); - AssertOnTimeout($"Client-{m_ClientNetworkManagers[0].LocalClientId} failed to spawn {nameof(NetworkObject)} id-{authorityNetworkObject.NetworkObjectId}!"); - - var clientNetworkObject = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][authorityNetworkObject.NetworkObjectId]; - var clientPreSpawn = clientNetworkObject.GetComponent(); - var clientPostSpawn = clientNetworkObject.GetComponent(); - - Assert.IsTrue(authorityPreSpawn.OnNetworkPreSpawnCalled, $"[Authority-side] OnNetworkPreSpawn not invoked!"); - Assert.IsTrue(clientPreSpawn.OnNetworkPreSpawnCalled, $"[Client-side] OnNetworkPreSpawn not invoked!"); - Assert.IsTrue(authorityPostSpawn.OnNetworkPostSpawnCalled, $"[Authority-side] OnNetworkPostSpawn not invoked!"); - Assert.IsTrue(clientPostSpawn.OnNetworkPostSpawnCalled, $"[Client-side] OnNetworkPostSpawn not invoked!"); - - Assert.IsTrue(authorityPreSpawn.NetworkVarValueMatches, $"[Authority-side][PreSpawn] Value {NetworkBehaviourPreSpawn.ValueToSet} does not match {authorityPreSpawn.TestNetworkVariable.Value}!"); - Assert.IsTrue(clientPreSpawn.NetworkVarValueMatches, $"[Client-side][PreSpawn] Value {NetworkBehaviourPreSpawn.ValueToSet} does not match {clientPreSpawn.TestNetworkVariable.Value}!"); - - Assert.IsTrue(authorityPostSpawn.ValueSet == NetworkBehaviourPreSpawn.ValueToSet, $"[Authority-side][PostSpawn] Value {NetworkBehaviourPreSpawn.ValueToSet} does not match {authorityPostSpawn.ValueSet}!"); - Assert.IsTrue(clientPostSpawn.ValueSet == NetworkBehaviourPreSpawn.ValueToSet, $"[Client-side][PostSpawn] Value {NetworkBehaviourPreSpawn.ValueToSet} does not match {clientPostSpawn.ValueSet}!"); - } - } -} diff --git a/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs.meta b/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs.meta deleted file mode 100644 index 70ad282..0000000 --- a/Tests/Runtime/NetworkBehaviourPrePostSpawnTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2263d66f6df15a7428d279dbdaba1519 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkBehaviourUpdaterTests.cs b/Tests/Runtime/NetworkBehaviourUpdaterTests.cs deleted file mode 100644 index a7b0fc9..0000000 --- a/Tests/Runtime/NetworkBehaviourUpdaterTests.cs +++ /dev/null @@ -1,305 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// This is a refactor of the original test's NetworkBehaviour INetVarInfo derived NetworkBehaviours - /// - internal class NetVarContainer : NetworkBehaviour - { - public enum NetVarsToCheck - { - One, - Two - } - - public NetVarsToCheck NumberOfNetVarsToCheck; - public int ValueToSetNetVarTo = 0; - - /// - /// Only used on the client-side for this test, this - /// is used to see if the network variables have changed. - /// - public bool HaveAllValuesChanged(int valueToCheck) - { - var allValuesChanged = false; - switch (NumberOfNetVarsToCheck) - { - case NetVarsToCheck.Two: - { - allValuesChanged = m_FirstValue.Value == valueToCheck && m_SeconValue.Value == valueToCheck; - break; - } - case NetVarsToCheck.One: - { - allValuesChanged = m_FirstValue.Value == valueToCheck; - break; - } - } - return allValuesChanged; - } - - /// - /// Only used on the server side to check the isDirty flag for the - /// NetworkVariables being used for each test iteration - /// - public bool AreNetVarsDirty() - { - var areDirty = false; - switch (NumberOfNetVarsToCheck) - { - case NetVarsToCheck.Two: - { - areDirty = m_FirstValue.IsDirty() && m_SeconValue.IsDirty(); - break; - } - case NetVarsToCheck.One: - { - areDirty = m_FirstValue.IsDirty(); - break; - } - } - - return areDirty; - } - - /// - /// The original version of this test only ever had up to 2 NetworkVariables per - /// NetworkBehaviour. As opposed to using a List of NetworkVariables, we just - /// create the maximum number that could be used and then only use what we need - /// for each test iteration. - /// - private NetworkVariable m_FirstValue = new NetworkVariable(); - private NetworkVariable m_SeconValue = new NetworkVariable(); - - public void SetOwnerWrite() - { - m_FirstValue = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - m_SeconValue = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - } - - public override void OnNetworkSpawn() - { - // Non-Authority will register each NetworkObject when it is spawned - if ((NetworkManager.DistributedAuthorityMode && !IsOwner) || (!NetworkManager.DistributedAuthorityMode && !IsServer)) - { - NetworkBehaviourUpdaterTests.ClientSideNotifyObjectSpawned(gameObject); - } - } - - /// - /// Server side only, sets the NetworkVariables being used to the ValueToSetNetVarTo - /// that is pre-configured when the Network Prefab is created. - /// - public void SetNetworkVariableValues() - { - if ((NetworkManager.DistributedAuthorityMode && IsOwner) || (!NetworkManager.DistributedAuthorityMode && IsServer)) - { - switch (NumberOfNetVarsToCheck) - { - case NetVarsToCheck.Two: - { - m_FirstValue.Value = ValueToSetNetVarTo; - m_SeconValue.Value = ValueToSetNetVarTo; - Assert.True(AreNetVarsDirty(), "Not all NetworkVariables were marked dirty on server after spawned!"); - break; - } - case NetVarsToCheck.One: - { - m_FirstValue.Value = ValueToSetNetVarTo; - Assert.True(AreNetVarsDirty(), "Not all NetworkVariables were marked dirty on server after spawned!"); - break; - } - } - } - } - } - - /// - /// Used to define how many NetworkVariables to use per NetVarContainer instance. - /// There are always two - /// - internal struct NetVarCombinationTypes - { - public NetVarContainer.NetVarsToCheck FirstType; - public NetVarContainer.NetVarsToCheck SecondType; - } - - /// - /// Server and Distributed Authority modes require at least 1 client while the host does not. - /// - /// [Host or Server mode][Number of Clients][First NetVar Type][Second NetVar Type] - [TestFixture(HostOrServer.DAHost, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.DAHost, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.DAHost, 1, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.DAHost, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.DAHost, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.DAHost, 2, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Server, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.Server, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Server, 1, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Server, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.Server, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Server, 2, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 0, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.Host, 0, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 0, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.Host, 1, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 1, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.One)] - [TestFixture(HostOrServer.Host, 2, NetVarContainer.NetVarsToCheck.One, NetVarContainer.NetVarsToCheck.Two)] - [TestFixture(HostOrServer.Host, 2, NetVarContainer.NetVarsToCheck.Two, NetVarContainer.NetVarsToCheck.Two)] - internal class NetworkBehaviourUpdaterTests : NetcodeIntegrationTest - { - // Go ahead and create maximum number of clients (not all tests will use them) - protected override int NumberOfClients => m_NumberOfClients; - public const int NetVarValueToSet = 1; - private static List s_ClientSpawnedNetworkObjects = new List(); - private GameObject m_PrefabToSpawn; - private NetVarCombinationTypes m_NetVarCombinationTypes; - private int m_NumberOfClients = 0; - - public NetworkBehaviourUpdaterTests(HostOrServer hostOrServer, int numberOfClients, NetVarContainer.NetVarsToCheck first, NetVarContainer.NetVarsToCheck second) : base(hostOrServer) - { - m_NetVarCombinationTypes = new NetVarCombinationTypes() - { - FirstType = first, - SecondType = second - }; - m_NumberOfClients = numberOfClients; - } - - protected override IEnumerator OnSetup() - { - s_ClientSpawnedNetworkObjects.Clear(); - return base.OnSetup(); - } - - /// - /// Clients will call this when NetworkObjects are spawned on their end - /// - /// the GameObject of the NetworkObject spawned - public static void ClientSideNotifyObjectSpawned(GameObject objectSpaned) - { - if (!s_ClientSpawnedNetworkObjects.Contains(objectSpaned)) - { - s_ClientSpawnedNetworkObjects.Add(objectSpaned); - } - } - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("NetVarCont"); - // Create the two instances of the NetVarContainer components and add them to the - // GameObject of this prefab - var netVarContainer = m_PrefabToSpawn.AddComponent(); - netVarContainer.NumberOfNetVarsToCheck = m_NetVarCombinationTypes.FirstType; - if (m_NetworkTopologyType == NetworkTopologyTypes.DistributedAuthority) - { - netVarContainer.SetOwnerWrite(); - } - - netVarContainer.ValueToSetNetVarTo = NetVarValueToSet; - netVarContainer = m_PrefabToSpawn.AddComponent(); - - if (m_NetworkTopologyType == NetworkTopologyTypes.DistributedAuthority) - { - netVarContainer.SetOwnerWrite(); - } - - netVarContainer.NumberOfNetVarsToCheck = m_NetVarCombinationTypes.SecondType; - netVarContainer.ValueToSetNetVarTo = NetVarValueToSet; - - base.OnServerAndClientsCreated(); - } - - /// - /// The updated BehaviourUpdaterAllTests was re-designed to replicate the same functionality being tested in the - /// original version of this test with additional time out handling and a re-organization in the order of operations. - /// Things like making sure all clients have spawned the NetworkObjects in question prior to testing for the - /// NetworkVariable value changes helped to eliminate the timing issues that were happening when this test was run - /// in a stand alone test runner build (i.e. all consoles run the stand alone version as opposed to the in-editor - /// version like the desktop tests use). - /// This update also updated how the server and clients were being constructed to help reduce the execution time. - /// - /// whether to run the server as a host or not - /// number of NetworkObjects to be spawned - [UnityTest] - public IEnumerator BehaviourUpdaterAllTests([Values(1, 2)] int numToSpawn) - { - // Tracks the server-side spawned prefab instances - var spawnedPrefabs = new List(); - - // Used to determine if the client-side checks of this test should be - // executed or not as well is used to make sure all clients have spawned - // the appropriate number of NetworkObjects with the NetVarContainer behaviour - var numberOfObjectsToSpawn = numToSpawn * NumberOfClients; - - var authority = m_NetworkTopologyType == NetworkTopologyTypes.DistributedAuthority ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - - // spawn the objects - for (int i = 0; i < numToSpawn; i++) - { - var spawnedObject = Object.Instantiate(m_PrefabToSpawn); - spawnedPrefabs.Add(spawnedObject); - var networkSpawnedObject = spawnedObject.GetComponent(); - networkSpawnedObject.NetworkManagerOwner = authority; - networkSpawnedObject.Spawn(); - } - - // Waits for all clients to spawn the NetworkObjects - yield return WaitForConditionOrTimeOut(() => numberOfObjectsToSpawn == s_ClientSpawnedNetworkObjects.Count); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for clients to report spawning objects! " + - $"Total reported client-side spawned objects {s_ClientSpawnedNetworkObjects.Count}"); - - - // Once all clients have spawned the NetworkObjects, set the network variables for - // those NetworkObjects on the server-side. - foreach (var spawnedPrefab in spawnedPrefabs) - { - var netVarContiners = spawnedPrefab.GetComponents(); - foreach (var netVarContiner in netVarContiners) - { - netVarContiner.SetNetworkVariableValues(); - } - } - - // Update the NetworkBehaviours to make sure all network variables are no longer marked as dirty - authority.BehaviourUpdater.NetworkBehaviourUpdate(); - - // Verify that all network variables are no longer dirty on server side only if we have clients (including host) - foreach (var spawnedPrefab in spawnedPrefabs) - { - var netVarContainers = spawnedPrefab.GetComponents(); - foreach (var netVarContainer in netVarContainers) - { - Assert.False(netVarContainer.AreNetVarsDirty(), "Some NetworkVariables were still marked dirty after NetworkBehaviourUpdate!"); - } - } - - // Get a list of all NetVarContainer components on the client-side spawned NetworkObjects - var clientSideNetVarContainers = new List(); - foreach (var clientSpawnedObjects in s_ClientSpawnedNetworkObjects) - { - var netVarContainers = clientSpawnedObjects.GetComponents(); - foreach (var netvarContiner in netVarContainers) - { - clientSideNetVarContainers.Add(netvarContiner); - } - } - - yield return WaitForConditionOrTimeOut(() => - clientSideNetVarContainers.Where(d => - d.HaveAllValuesChanged(NetVarValueToSet)).Count() == clientSideNetVarContainers.Count); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client side NetVarContainers to report all NetworkVariables have been updated!"); - } - } -} diff --git a/Tests/Runtime/NetworkBehaviourUpdaterTests.cs.meta b/Tests/Runtime/NetworkBehaviourUpdaterTests.cs.meta deleted file mode 100644 index 594d533..0000000 --- a/Tests/Runtime/NetworkBehaviourUpdaterTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ef76141a46cb34c44a8ca73bc15d2bd6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs b/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs deleted file mode 100644 index a43bd24..0000000 --- a/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkManagerCustomMessageManagerTests - { - [Test] - public void CustomMessageManagerAssigned() - { - var gameObject = new GameObject(nameof(CustomMessageManagerAssigned)); - var networkManager = gameObject.AddComponent(); - var transport = gameObject.AddComponent(); - - networkManager.NetworkConfig = new NetworkConfig - { - // Set dummy transport that does nothing - NetworkTransport = transport - }; - - CustomMessagingManager preManager = networkManager.CustomMessagingManager; - - // Start server to cause initialization - networkManager.StartServer(); - - Debug.Assert(preManager == null); - Debug.Assert(networkManager.CustomMessagingManager != null); - - - networkManager.Shutdown(); - Object.DestroyImmediate(gameObject); - } - } -} diff --git a/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs.meta b/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs.meta deleted file mode 100644 index a25df43..0000000 --- a/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 315ffe39806441839400d21871d566a0 -timeCreated: 1618478909 \ No newline at end of file diff --git a/Tests/Runtime/NetworkManagerEventsTests.cs b/Tests/Runtime/NetworkManagerEventsTests.cs deleted file mode 100644 index 8b1c993..0000000 --- a/Tests/Runtime/NetworkManagerEventsTests.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkManagerEventsTests - { - private NetworkManager m_ClientManager; - private NetworkManager m_ServerManager; - - private NetworkManager m_NetworkManagerInstantiated; - private bool m_Instantiated; - private bool m_Destroyed; - - /// - /// Validates the and event notifications - /// - [UnityTest] - public IEnumerator InstantiatedAndDestroyingNotifications() - { - NetworkManager.OnInstantiated += NetworkManager_OnInstantiated; - NetworkManager.OnDestroying += NetworkManager_OnDestroying; - var waitPeriod = new WaitForSeconds(0.01f); - var prefab = new GameObject("InstantiateDestroy"); - var networkManagerPrefab = prefab.AddComponent(); - - Assert.IsTrue(m_Instantiated, $"{nameof(NetworkManager)} prefab did not get instantiated event notification!"); - Assert.IsTrue(m_NetworkManagerInstantiated == networkManagerPrefab, $"{nameof(NetworkManager)} prefab parameter did not match!"); - - m_Instantiated = false; - m_NetworkManagerInstantiated = null; - - for (int i = 0; i < 3; i++) - { - var instance = Object.Instantiate(prefab); - var networkManager = instance.GetComponent(); - Assert.IsTrue(m_Instantiated, $"{nameof(NetworkManager)} instance-{i} did not get instantiated event notification!"); - Assert.IsTrue(m_NetworkManagerInstantiated == networkManager, $"{nameof(NetworkManager)} instance-{i} parameter did not match!"); - Object.DestroyImmediate(instance); - Assert.IsTrue(m_Destroyed, $"{nameof(NetworkManager)} instance-{i} did not get destroying event notification!"); - m_Instantiated = false; - m_NetworkManagerInstantiated = null; - m_Destroyed = false; - } - m_NetworkManagerInstantiated = networkManagerPrefab; - Object.Destroy(prefab); - yield return null; - Assert.IsTrue(m_Destroyed, $"{nameof(NetworkManager)} prefab did not get destroying event notification!"); - NetworkManager.OnInstantiated -= NetworkManager_OnInstantiated; - NetworkManager.OnDestroying -= NetworkManager_OnDestroying; - } - - private void NetworkManager_OnInstantiated(NetworkManager networkManager) - { - m_Instantiated = true; - m_NetworkManagerInstantiated = networkManager; - } - - private void NetworkManager_OnDestroying(NetworkManager networkManager) - { - m_Destroyed = true; - Assert.True(m_NetworkManagerInstantiated == networkManager, $"Destroying {nameof(NetworkManager)} and current instance is not a match for the one passed into the event!"); - } - - [UnityTest] - public IEnumerator OnServerStoppedCalledWhenServerStops() - { - bool callbackInvoked = false; - var gameObject = new GameObject(nameof(OnServerStoppedCalledWhenServerStops)); - m_ServerManager = gameObject.AddComponent(); - - // Set dummy transport that does nothing - var transport = gameObject.AddComponent(); - m_ServerManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - Action onServerStopped = (bool wasAlsoClient) => - { - callbackInvoked = true; - Assert.IsFalse(wasAlsoClient); - }; - - // Start server to cause initialization process - Assert.True(m_ServerManager.StartServer()); - Assert.True(m_ServerManager.IsListening); - - m_ServerManager.OnServerStopped += onServerStopped; - m_ServerManager.Shutdown(); - Object.DestroyImmediate(gameObject); - - yield return WaitUntilManagerShutsdown(); - - Assert.False(m_ServerManager.IsListening); - Assert.True(callbackInvoked, "OnServerStopped wasn't invoked"); - } - - [UnityTest] - public IEnumerator OnClientStoppedCalledWhenClientStops() - { - yield return InitializeServerAndAClient(); - - bool callbackInvoked = false; - Action onClientStopped = (bool wasAlsoServer) => - { - callbackInvoked = true; - Assert.IsFalse(wasAlsoServer); - }; - - m_ClientManager.OnClientStopped += onClientStopped; - m_ClientManager.Shutdown(); - yield return WaitUntilManagerShutsdown(); - - Assert.True(callbackInvoked, "OnClientStopped wasn't invoked"); - } - - [UnityTest] - public IEnumerator OnClientAndServerStoppedCalledWhenHostStops() - { - var gameObject = new GameObject(nameof(OnClientAndServerStoppedCalledWhenHostStops)); - m_ServerManager = gameObject.AddComponent(); - - // Set dummy transport that does nothing - var transport = gameObject.AddComponent(); - m_ServerManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - int callbacksInvoked = 0; - Action onClientStopped = (bool wasAlsoServer) => - { - callbacksInvoked++; - Assert.IsTrue(wasAlsoServer); - }; - - Action onServerStopped = (bool wasAlsoClient) => - { - callbacksInvoked++; - Assert.IsTrue(wasAlsoClient); - }; - - // Start server to cause initialization process - Assert.True(m_ServerManager.StartHost()); - Assert.True(m_ServerManager.IsListening); - - m_ServerManager.OnServerStopped += onServerStopped; - m_ServerManager.OnClientStopped += onClientStopped; - m_ServerManager.Shutdown(); - Object.DestroyImmediate(gameObject); - - yield return WaitUntilManagerShutsdown(); - - Assert.False(m_ServerManager.IsListening); - Assert.AreEqual(2, callbacksInvoked, "either OnServerStopped or OnClientStopped wasn't invoked"); - } - - [UnityTest] - public IEnumerator OnServerStartedCalledWhenServerStarts() - { - var gameObject = new GameObject(nameof(OnServerStartedCalledWhenServerStarts)); - m_ServerManager = gameObject.AddComponent(); - - // Set dummy transport that does nothing - var transport = gameObject.AddComponent(); - m_ServerManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - bool callbackInvoked = false; - Action onServerStarted = () => - { - callbackInvoked = true; - if (!m_ServerManager.IsServer) - { - Assert.Fail("OnServerStarted called when the server is not active yet"); - } - }; - - // Start server to cause initialization process - m_ServerManager.OnServerStarted += onServerStarted; - - Assert.True(m_ServerManager.StartServer()); - Assert.True(m_ServerManager.IsListening); - - yield return WaitUntilServerBufferingIsReady(); - - Assert.True(callbackInvoked, "OnServerStarted wasn't invoked"); - } - - [UnityTest] - public IEnumerator OnClientStartedCalledWhenClientStarts() - { - bool callbackInvoked = false; - Action onClientStarted = () => - { - callbackInvoked = true; - if (!m_ClientManager.IsClient) - { - Assert.Fail("onClientStarted called when the client is not active yet"); - } - }; - - yield return InitializeServerAndAClient(onClientStarted); - - Assert.True(callbackInvoked, "OnClientStarted wasn't invoked"); - } - - [UnityTest] - public IEnumerator OnClientAndServerStartedCalledWhenHostStarts() - { - var gameObject = new GameObject(nameof(OnClientAndServerStartedCalledWhenHostStarts)); - m_ServerManager = gameObject.AddComponent(); - - // Set dummy transport that does nothing - var transport = gameObject.AddComponent(); - m_ServerManager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - int callbacksInvoked = 0; - Action onClientStarted = () => - { - callbacksInvoked++; - }; - - Action onServerStarted = () => - { - callbacksInvoked++; - }; - - m_ServerManager.OnServerStarted += onServerStarted; - m_ServerManager.OnClientStarted += onClientStarted; - - // Start server to cause initialization process - Assert.True(m_ServerManager.StartHost()); - Assert.True(m_ServerManager.IsListening); - - yield return WaitUntilServerBufferingIsReady(); - Assert.AreEqual(2, callbacksInvoked, "either OnServerStarted or OnClientStarted wasn't invoked"); - } - - private IEnumerator WaitUntilManagerShutsdown() - { - /* Need two updates to actually shut down. First one to see the transport failing, which - marks the NetworkManager as shutting down. Second one where actual shutdown occurs. */ - yield return null; - yield return null; - } - - private IEnumerator InitializeServerAndAClient(Action onClientStarted = null) - { - // Create multiple NetworkManager instances - if (!NetcodeIntegrationTestHelpers.Create(1, out m_ServerManager, out NetworkManager[] clients, 30)) - { - Debug.LogError("Failed to create instances"); - Assert.Fail("Failed to create instances"); - } - - // passing no clients on purpose to start them manually later - NetcodeIntegrationTestHelpers.Start(false, m_ServerManager, new NetworkManager[] { }); - - yield return WaitUntilServerBufferingIsReady(); - m_ClientManager = clients[0]; - - if (onClientStarted != null) - { - m_ClientManager.OnClientStarted += onClientStarted; - } - - Assert.True(m_ClientManager.StartClient()); - NetcodeIntegrationTestHelpers.RegisterHandlers(clients[0]); - // Wait for connection on client side - yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients); - } - - private IEnumerator WaitUntilServerBufferingIsReady() - { - /* wait until at least more than 2 server ticks have passed - Note: Waiting for more than 2 ticks on the server is due - to the time system applying buffering to the received time - in NetworkTimeSystem.Sync */ - yield return new WaitUntil(() => m_ServerManager.NetworkTickSystem.ServerTime.Tick > 2); - } - - [UnityTearDown] - public virtual IEnumerator Teardown() - { - NetcodeIntegrationTestHelpers.Destroy(); - if (m_ServerManager != null) - { - m_ServerManager.ShutdownInternal(); - Object.DestroyImmediate(m_ServerManager); - m_ServerManager = null; - } - if (m_ClientManager != null) - { - m_ClientManager.ShutdownInternal(); - Object.DestroyImmediate(m_ClientManager); - m_ClientManager = null; - } - yield return null; - } - } -} diff --git a/Tests/Runtime/NetworkManagerEventsTests.cs.meta b/Tests/Runtime/NetworkManagerEventsTests.cs.meta deleted file mode 100644 index 996ba3b..0000000 --- a/Tests/Runtime/NetworkManagerEventsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 238d8724ba5ce3947bc20f5d6c056b6e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkManagerSceneManagerTests.cs b/Tests/Runtime/NetworkManagerSceneManagerTests.cs deleted file mode 100644 index d7544b7..0000000 --- a/Tests/Runtime/NetworkManagerSceneManagerTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkManagerSceneManagerTests - { - [Test] - public void SceneManagerAssigned() - { - var gameObject = new GameObject(nameof(SceneManagerAssigned)); - var networkManager = gameObject.AddComponent(); - var transport = gameObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - // Set dummy transport that does nothing - NetworkTransport = transport - }; - - NetworkSceneManager preManager = networkManager.SceneManager; - - // Start server to cause initialization process - networkManager.StartServer(); - - Debug.Assert(preManager == null); - Debug.Assert(networkManager.SceneManager != null); - - Object.DestroyImmediate(gameObject); - } - } -} diff --git a/Tests/Runtime/NetworkManagerSceneManagerTests.cs.meta b/Tests/Runtime/NetworkManagerSceneManagerTests.cs.meta deleted file mode 100644 index fe94876..0000000 --- a/Tests/Runtime/NetworkManagerSceneManagerTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 9753bf4088484cbebee95d917699dec6 -timeCreated: 1618482634 \ No newline at end of file diff --git a/Tests/Runtime/NetworkManagerTransportTests.cs b/Tests/Runtime/NetworkManagerTransportTests.cs deleted file mode 100644 index 788758c..0000000 --- a/Tests/Runtime/NetworkManagerTransportTests.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkManagerTransportTests - { - [Test] - public void ClientDoesNotStartWhenTransportFails() - { - bool callbackInvoked = false; - Action onTransportFailure = () => { callbackInvoked = true; }; - - var manager = new GameObject().AddComponent(); - manager.OnTransportFailure += onTransportFailure; - - var transport = manager.gameObject.AddComponent(); - transport.FailOnStart = true; - - manager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - LogAssert.Expect(LogType.Error, $"[Netcode] Client is shutting down due to network transport start failure of {transport.GetType().Name}!"); - - Assert.False(manager.StartClient()); - Assert.False(manager.IsListening); - Assert.False(manager.IsConnectedClient); - - Assert.True(callbackInvoked); - } - - [Test] - public void HostDoesNotStartWhenTransportFails() - { - bool callbackInvoked = false; - Action onTransportFailure = () => { callbackInvoked = true; }; - - var manager = new GameObject().AddComponent(); - manager.OnTransportFailure += onTransportFailure; - - var transport = manager.gameObject.AddComponent(); - transport.FailOnStart = true; - - manager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - LogAssert.Expect(LogType.Error, $"[Netcode] Host is shutting down due to network transport start failure of {transport.GetType().Name}!"); - - Assert.False(manager.StartHost()); - Assert.False(manager.IsListening); - - Assert.True(callbackInvoked); - } - - [Test] - public void ServerDoesNotStartWhenTransportFails() - { - bool callbackInvoked = false; - Action onTransportFailure = () => { callbackInvoked = true; }; - - var manager = new GameObject().AddComponent(); - manager.OnTransportFailure += onTransportFailure; - - var transport = manager.gameObject.AddComponent(); - transport.FailOnStart = true; - - manager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - LogAssert.Expect(LogType.Error, $"[Netcode] Server is shutting down due to network transport start failure of {transport.GetType().Name}!"); - - Assert.False(manager.StartServer()); - Assert.False(manager.IsListening); - - Assert.True(callbackInvoked); - } - - [UnityTest] - public IEnumerator ShutsDownWhenTransportFails() - { - bool callbackInvoked = false; - Action onTransportFailure = () => { callbackInvoked = true; }; - - var manager = new GameObject().AddComponent(); - manager.OnTransportFailure += onTransportFailure; - - var transport = manager.gameObject.AddComponent(); - transport.FailOnNextPoll = true; - - manager.NetworkConfig = new NetworkConfig() { NetworkTransport = transport }; - - Assert.True(manager.StartServer()); - Assert.True(manager.IsListening); - - LogAssert.Expect(LogType.Error, $"[Netcode] Server is shutting down due to network transport failure of {transport.GetType().Name}!"); - - // Need two updates to actually shut down. First one to see the transport failing, which - // marks the NetworkManager as shutting down. Second one where actual shutdown occurs. - yield return null; - yield return null; - - Assert.False(manager.IsListening); - Assert.True(callbackInvoked); - } - - /// - /// Does nothing but simulate a transport that can fail at startup and/or when polling events. - /// - internal class FailedTransport : TestingNetworkTransport - { - public bool FailOnStart = false; - public bool FailOnNextPoll = false; - - public override bool StartClient() => !FailOnStart; - - public override bool StartServer() => !FailOnStart; - - public override NetworkEvent PollEvent(out ulong clientId, out ArraySegment payload, out float receiveTime) - { - clientId = 0; - payload = new ArraySegment(); - receiveTime = 0; - - if (FailOnNextPoll) - { - FailOnNextPoll = false; - return NetworkEvent.TransportFailure; - } - else - { - return NetworkEvent.Nothing; - } - } - - public override ulong ServerClientId => 0; - - public override void Send(ulong clientId, ArraySegment payload, NetworkDelivery networkDelivery) - { - } - - public override void Initialize(NetworkManager networkManager = null) - { - } - - public override void Shutdown() - { - } - - public override ulong GetCurrentRtt(ulong clientId) => 0; - - public override void DisconnectRemoteClient(ulong clientId) - { - } - - public override void DisconnectLocalClient() - { - } - } - } -} diff --git a/Tests/Runtime/NetworkManagerTransportTests.cs.meta b/Tests/Runtime/NetworkManagerTransportTests.cs.meta deleted file mode 100644 index 134ba9f..0000000 --- a/Tests/Runtime/NetworkManagerTransportTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 798d76599e527b245a14b7cc9cfd2607 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject.meta b/Tests/Runtime/NetworkObject.meta deleted file mode 100644 index 3b96bc2..0000000 --- a/Tests/Runtime/NetworkObject.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3a1f0974a98eaa1498ac39be872eeed4 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs deleted file mode 100644 index 64820cb..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Tests calling destroy on spawned / unspawned s. Expected behavior: - /// - Server or client destroy on unspawned => Object gets destroyed, no exceptions - /// - Server destroy spawned => Object gets destroyed and despawned/destroyed on all clients. Server does not run . Client runs it. - /// - Client destroy spawned => throw exception. - /// - - - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(NetworkTopologyTypes.ClientServer)] - internal class NetworkObjectDestroyTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - public NetworkObjectDestroyTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - - /// - /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. - /// - /// - [UnityTest] - public IEnumerator TestNetworkObjectAuthorityDestroy() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ServerNetworkManager, serverClientPlayerResult); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation(x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, m_ClientNetworkManagers[0], clientClientPlayerResult); - - Assert.IsNotNull(serverClientPlayerResult.Result.gameObject); - Assert.IsNotNull(clientClientPlayerResult.Result.gameObject); - - var targetNetworkManager = m_ClientNetworkManagers[0]; - if (m_DistributedAuthority) - { - targetNetworkManager = m_ClientNetworkManagers[1]; - // destroy the authoritative player (distributed authority) - Object.Destroy(clientClientPlayerResult.Result.gameObject); - } - else - { - // destroy the authoritative player (client-server) - Object.Destroy(serverClientPlayerResult.Result.gameObject); - } - - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeHandled(targetNetworkManager); - - Assert.IsTrue(serverClientPlayerResult.Result == null); // Assert.IsNull doesn't work here - Assert.IsTrue(clientClientPlayerResult.Result == null); - - // validate that any unspawned networkobject can be destroyed - var go = new GameObject(); - go.AddComponent(); - Object.Destroy(go); - - yield return null; - Assert.IsTrue(go == null); - } - - - public enum ClientDestroyObject - { - ShuttingDown, - ActiveSession - } - - private string m_ClientPlayerName; - private ulong m_ClientNetworkObjectId; - /// - /// Validates the expected behavior when the client-side destroys a - /// - [UnityTest] - public IEnumerator TestNetworkObjectClientDestroy([Values] ClientDestroyObject clientDestroyObject) - { - var isShuttingDown = clientDestroyObject == ClientDestroyObject.ShuttingDown; - var clientPlayer = m_ClientNetworkManagers[0].LocalClient.PlayerObject; - var clientId = clientPlayer.OwnerClientId; - - //destroying a NetworkObject while shutting down is allowed - if (isShuttingDown) - { - if (m_DistributedAuthority) - { - // Shutdown the 2nd client - m_ClientNetworkManagers[1].Shutdown(); - } - else - { - // Shutdown the - m_ClientNetworkManagers[0].Shutdown(); - } - } - else - { - LogAssert.ignoreFailingMessages = true; - NetworkLog.NetworkManagerOverride = m_ClientNetworkManagers[0]; - } - - m_ClientPlayerName = clientPlayer.gameObject.name; - m_ClientNetworkObjectId = clientPlayer.NetworkObjectId; - if (m_DistributedAuthority) - { - m_ClientPlayerName = m_PlayerNetworkObjects[m_ClientNetworkManagers[1].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].gameObject.name; - m_ClientNetworkObjectId = m_PlayerNetworkObjects[m_ClientNetworkManagers[1].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].NetworkObjectId; - - if (!isShuttingDown) - { - NetworkLog.NetworkManagerOverride = m_ClientNetworkManagers[1]; - } - // the 2nd client attempts to destroy the 1st client's player object (if shutting down then "ok" if not then not "ok") - Object.DestroyImmediate(m_PlayerNetworkObjects[m_ClientNetworkManagers[1].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].gameObject); - } - else - { - // the 1st client attempts to destroy its own player object (if shutting down then "ok" if not then not "ok") - Object.DestroyImmediate(m_ClientNetworkManagers[0].LocalClient.PlayerObject.gameObject); - } - - // destroying a NetworkObject while a session is active is not allowed - if (!isShuttingDown) - { - yield return WaitForConditionOrTimeOut(HaveLogsBeenReceived); - AssertOnTimeout($"Not all expected logs were received when destroying a {nameof(NetworkObject)} on the client side during an active session!"); - } - } - - private bool HaveLogsBeenReceived() - { - if (m_DistributedAuthority) - { - if (!NetcodeLogAssert.HasLogBeenReceived(LogType.Error, $"[Netcode] [Invalid Destroy][{m_ClientPlayerName}][NetworkObjectId:{m_ClientNetworkObjectId}] Destroy a spawned {nameof(NetworkObject)} on a non-owner client is not valid during a distributed authority session. Call Destroy or Despawn on the client-owner instead.")) - { - return false; - } - } - else - { - if (!NetcodeLogAssert.HasLogBeenReceived(LogType.Error, $"[Netcode] [Invalid Destroy][{m_ClientPlayerName}][NetworkObjectId:{m_ClientNetworkObjectId}] Destroy a spawned {nameof(NetworkObject)} on a non-host client is not valid. Call Destroy or Despawn on the server/host instead.")) - { - return false; - } - - if (!NetcodeLogAssert.HasLogBeenReceived(LogType.Error, $"[Netcode-Server Sender={m_ClientNetworkManagers[0].LocalClientId}] [Invalid Destroy][{m_ClientPlayerName}][NetworkObjectId:{m_ClientNetworkObjectId}] Destroy a spawned {nameof(NetworkObject)} on a non-host client is not valid. Call Destroy or Despawn on the server/host instead.")) - { - return false; - } - } - return true; - } - - protected override IEnumerator OnTearDown() - { - NetworkLog.NetworkManagerOverride = null; - LogAssert.ignoreFailingMessages = false; - return base.OnTearDown(); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs.meta deleted file mode 100644 index 76a6f7f..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectDestroyTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: adef71bb3a6193e498dedf91a2f378b9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs deleted file mode 100644 index 51e86ea..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class NetworkObjectDontDestroyWithOwnerTests : NetcodeIntegrationTest - { - private const int k_NumberObjectsToSpawn = 32; - protected override int NumberOfClients => 1; - - protected GameObject m_PrefabToSpawn; - - public NetworkObjectDontDestroyWithOwnerTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("ClientOwnedObject"); - m_PrefabToSpawn.GetComponent().DontDestroyWithOwner = true; - } - - [UnityTest] - public IEnumerator DontDestroyWithOwnerTest() - { - var client = m_ClientNetworkManagers[0]; - var clientId = client.LocalClientId; - var networkObjects = SpawnObjects(m_PrefabToSpawn, m_ClientNetworkManagers[0], k_NumberObjectsToSpawn); - - // wait for object spawn on client to reach k_NumberObjectsToSpawn + 1 (k_NumberObjectsToSpawn and 1 for the player) - yield return WaitForConditionOrTimeOut(() => client.SpawnManager.GetClientOwnedObjects(clientId).Count() == k_NumberObjectsToSpawn + 1); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to have 33 NetworkObjects spawned! Only {client.SpawnManager.GetClientOwnedObjects(clientId).Count()} were assigned!"); - - // Since clients spawn their objects locally in distributed authority mode, we have to rebuild the list of the client - // owned objects on the (DAHost) server-side because when the client disconnects it will destroy its local instances. - if (m_DistributedAuthority) - { - networkObjects.Clear(); - var serversideClientOwnedObjects = m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(clientId); - - foreach (var networkObject in serversideClientOwnedObjects) - { - if (!networkObject.IsPlayerObject) - { - networkObjects.Add(networkObject.gameObject); - } - } - } - - // disconnect the client that owns all the clients - NetcodeIntegrationTestHelpers.StopOneClient(client); - - var remainingClients = Mathf.Max(0, TotalClients - 1); - // wait for disconnect - yield return WaitForConditionOrTimeOut(() => m_ServerNetworkManager.ConnectedClients.Count == remainingClients); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client to disconnect!"); - - for (int i = 0; i < networkObjects.Count; i++) - { - var networkObject = networkObjects[i].GetComponent(); - // ensure ownership was transferred back - Assert.That(networkObject.OwnerClientId == m_ServerNetworkManager.LocalClientId); - } - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs.meta deleted file mode 100644 index 9e08ce6..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectDontDestroyWithOwnerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 216add57838067047b8f67fed02d6c71 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs deleted file mode 100644 index d9b0521..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkObjectNetworkClientOwnedObjectsTests : NetcodeIntegrationTest - { - private class DummyNetworkBehaviour : NetworkBehaviour - { - - } - - protected override int NumberOfClients => 1; - private GameObject m_NetworkObject; - - protected override void OnServerAndClientsCreated() - { - m_NetworkObject = CreateNetworkObjectPrefab("ClientOwnedObject"); - m_NetworkObject.gameObject.AddComponent(); - } - - [UnityTest] - public IEnumerator ChangeOwnershipOwnedObjectsAddTest() - { - NetworkObject serverObject = m_NetworkObject.GetComponent(); - serverObject.NetworkManagerOwner = m_ServerNetworkManager; - serverObject.Spawn(); - - // Provide enough time for the client to receive and process the spawned message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - // The object is owned by server - Assert.False(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId)); - - // Change the ownership - serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - // Provide enough time for the client to receive and process the change in ownership message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - // Ensure it's now added to the list - Assert.True(m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId)); - Assert.True(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId)); - } - - [UnityTest] - public IEnumerator WhenOwnershipIsChanged_OwnershipValuesUpdateCorrectly() - { - NetworkObject serverObject = m_NetworkObject.GetComponent(); - serverObject.NetworkManagerOwner = m_ServerNetworkManager; - serverObject.Spawn(); - - // Provide enough time for the client to receive and process the spawned message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - // The object is owned by server - Assert.False(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId)); - - // Change the ownership - serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - // Provide enough time for the client to receive and process the change in ownership message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsFalse(serverObject.IsOwner); - Assert.IsFalse(serverObject.IsOwnedByServer); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, serverObject.OwnerClientId); - - var serverBehaviour = serverObject.GetComponent(); - Assert.IsFalse(serverBehaviour.IsOwner); - Assert.IsFalse(serverBehaviour.IsOwnedByServer); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, serverBehaviour.OwnerClientId); - -#if UNITY_2023_1_OR_NEWER - var clientObject = Object.FindObjectsByType(FindObjectsSortMode.InstanceID).Where((obj) => obj.NetworkManagerOwner == m_ClientNetworkManagers[0]).FirstOrDefault(); -#else - var clientObject = Object.FindObjectsOfType().Where((obj) => obj.NetworkManagerOwner == m_ClientNetworkManagers[0]).FirstOrDefault(); -#endif - - - Assert.IsNotNull(clientObject); - Assert.IsTrue(clientObject.IsOwner); - Assert.IsFalse(clientObject.IsOwnedByServer); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, clientObject.OwnerClientId); - - var clientBehaviour = clientObject.GetComponent(); - Assert.IsTrue(clientBehaviour.IsOwner); - Assert.IsFalse(clientBehaviour.IsOwnedByServer); - Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, clientBehaviour.OwnerClientId); - - serverObject.RemoveOwnership(); - - // Provide enough time for the client to receive and process the change in ownership message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsTrue(serverObject.IsOwner); - Assert.IsTrue(serverObject.IsOwnedByServer); - Assert.AreEqual(NetworkManager.ServerClientId, serverObject.OwnerClientId); - Assert.IsTrue(serverBehaviour.IsOwner); - Assert.IsTrue(serverBehaviour.IsOwnedByServer); - Assert.AreEqual(NetworkManager.ServerClientId, serverBehaviour.OwnerClientId); - - Assert.IsFalse(clientObject.IsOwner); - Assert.IsTrue(clientObject.IsOwnedByServer); - Assert.AreEqual(NetworkManager.ServerClientId, clientObject.OwnerClientId); - Assert.IsFalse(clientBehaviour.IsOwner); - Assert.IsTrue(clientBehaviour.IsOwnedByServer); - Assert.AreEqual(NetworkManager.ServerClientId, clientBehaviour.OwnerClientId); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs.meta deleted file mode 100644 index 8470304..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 067d53283c8fa4c31b638b830473c5b7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs deleted file mode 100644 index 9a737a4..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Tests that check OnNetworkDespawn being invoked - /// - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class NetworkObjectOnNetworkDespawnTests : NetcodeIntegrationTest - { - private const string k_ObjectName = "TestDespawn"; - public enum InstanceTypes - { - Server, - Client - } - - protected override int NumberOfClients => 1; - private GameObject m_ObjectToSpawn; - private NetworkObject m_NetworkObject; - - private HostOrServer m_HostOrServer; - - public NetworkObjectOnNetworkDespawnTests(HostOrServer hostOrServer) : base(hostOrServer) - { - m_HostOrServer = hostOrServer; - } - - internal class OnNetworkDespawnTestComponent : NetworkBehaviour - { - public bool OnNetworkDespawnCalled { get; internal set; } - - public override void OnNetworkSpawn() - { - OnNetworkDespawnCalled = false; - base.OnNetworkSpawn(); - } - - public override void OnNetworkDespawn() - { - OnNetworkDespawnCalled = true; - base.OnNetworkDespawn(); - } - } - - protected override void OnServerAndClientsCreated() - { - m_ObjectToSpawn = CreateNetworkObjectPrefab(k_ObjectName); - m_ObjectToSpawn.AddComponent(); - base.OnServerAndClientsCreated(); - } - - private bool ObjectSpawnedOnAllNetworkManagerInstances() - { - if (!s_GlobalNetworkObjects.ContainsKey(m_ServerNetworkManager.LocalClientId)) - { - return false; - } - if (!s_GlobalNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_NetworkObject.NetworkObjectId)) - { - return false; - } - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (!s_GlobalNetworkObjects.ContainsKey(clientNetworkManager.LocalClientId)) - { - return false; - } - if (!s_GlobalNetworkObjects[clientNetworkManager.LocalClientId].ContainsKey(m_NetworkObject.NetworkObjectId)) - { - return false; - } - } - - return true; - } - - /// - /// This test validates that is invoked when the - /// is shutdown. - /// - [UnityTest] - public IEnumerator TestNetworkObjectDespawnOnShutdown([Values(InstanceTypes.Server, InstanceTypes.Client)] InstanceTypes despawnCheck) - { - var networkManager = despawnCheck == InstanceTypes.Server ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - var networkManagerOwner = m_ServerNetworkManager; - if (m_DistributedAuthority) - { - networkManagerOwner = networkManager; - } - - // Spawn the test object - var spawnedObject = SpawnObject(m_ObjectToSpawn, networkManagerOwner); - m_NetworkObject = spawnedObject.GetComponent(); - - - yield return WaitForConditionOrTimeOut(ObjectSpawnedOnAllNetworkManagerInstances); - AssertOnTimeout($"Timed out waiting for all {nameof(NetworkManager)} instances to spawn {m_NetworkObject.name}!"); - - // Get the spawned object relative to which NetworkManager instance we are testing. - var relativeSpawnedObject = s_GlobalNetworkObjects[networkManager.LocalClientId][m_NetworkObject.NetworkObjectId]; - var onNetworkDespawnTestComponent = relativeSpawnedObject.GetComponent(); - - // Confirm it is not set before shutting down the NetworkManager - Assert.IsFalse(onNetworkDespawnTestComponent.OnNetworkDespawnCalled, $"{nameof(OnNetworkDespawnTestComponent.OnNetworkDespawnCalled)} was set prior to shutting down!"); - - // Shutdown the NetworkManager instance we are testing. - networkManager.Shutdown(); - - // Confirm that OnNetworkDespawn is invoked after shutdown - yield return WaitForConditionOrTimeOut(() => onNetworkDespawnTestComponent.OnNetworkDespawnCalled); - AssertOnTimeout($"Timed out waiting for {nameof(NetworkObject)} instance to despawn on the {despawnCheck} side!"); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs.meta deleted file mode 100644 index 895a567..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOnNetworkDespawnTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 93f8ca7aa8b616746a1c15592830b047 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs deleted file mode 100644 index 841bad4..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs +++ /dev/null @@ -1,391 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(NetworkTopologyTypes.ClientServer)] - internal class NetworkObjectOnSpawnTests : NetcodeIntegrationTest - { - private GameObject m_TestNetworkObjectPrefab; - private GameObject m_TestNetworkObjectInstance; - - protected override int NumberOfClients => 2; - - public enum ObserverTestTypes - { - WithObservers, - WithoutObservers - } - private GameObject m_ObserverPrefab; - private NetworkObject m_ObserverTestNetworkObject; - private ObserverTestTypes m_ObserverTestType; - - private const string k_ObserverTestObjName = "ObsObj"; - private const string k_WithObserversError = "Not all clients spawned the"; - private const string k_WithoutObserversError = "A client spawned the"; - - public NetworkObjectOnSpawnTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - - protected override void OnServerAndClientsCreated() - { - m_ObserverPrefab = CreateNetworkObjectPrefab(k_ObserverTestObjName); - base.OnServerAndClientsCreated(); - } - - private bool CheckClientsSideObserverTestObj() - { - foreach (var client in m_ClientNetworkManagers) - { - if (m_ObserverTestType == ObserverTestTypes.WithObservers) - { - // When validating this portion of the test and spawning with observers is true, there - // should be spawned objects on the clients. - if (!s_GlobalNetworkObjects.ContainsKey(client.LocalClientId)) - { - return false; - } - } - else - { - // When validating this portion of the test and spawning with observers is false, there - // should be no spawned objects on the clients. - if (s_GlobalNetworkObjects.ContainsKey(client.LocalClientId)) - { - return false; - } - // We don't need to check anything else for spawn without observers - continue; - } - - var clientObjects = s_GlobalNetworkObjects[client.LocalClientId]; - // Make sure they did spawn the object - if (m_ObserverTestType == ObserverTestTypes.WithObservers) - { - if (!clientObjects.ContainsKey(m_ObserverTestNetworkObject.NetworkObjectId)) - { - return false; - } - if (!clientObjects[m_ObserverTestNetworkObject.NetworkObjectId].IsSpawned) - { - return false; - } - } - } - return true; - } - - /// - /// Assures the late joining client has all - /// NetworkPrefabs required to connect. - /// - protected override void OnNewClientCreated(NetworkManager networkManager) - { - foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) - { - if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab)) - { - networkManager.NetworkConfig.Prefabs.Add(networkPrefab); - } - } - networkManager.NetworkConfig.EnableSceneManagement = m_ServerNetworkManager.NetworkConfig.EnableSceneManagement; - base.OnNewClientCreated(networkManager); - } - - /// - /// This test validates property - /// - /// whether to spawn with or without observers - [UnityTest] - public IEnumerator ObserverSpawnTests([Values] ObserverTestTypes observerTestTypes, [Values] SceneManagementState sceneManagement) - { - if (sceneManagement == SceneManagementState.SceneManagementDisabled) - { - // When scene management is disabled, we need this wait period for all clients to be up to date with - // all other clients before beginning the process of stopping all clients. - if (m_DistributedAuthority) - { - yield return new WaitForSeconds(0.5f); - } - // Disable prefabs to prevent them from being destroyed - foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) - { - networkPrefab.Prefab.SetActive(false); - } - - // Shutdown and clean up the current client NetworkManager instances - foreach (var networkManager in m_ClientNetworkManagers) - { - m_PlayerNetworkObjects[networkManager.LocalClientId].Clear(); - m_PlayerNetworkObjects.Remove(networkManager.LocalClientId); - yield return StopOneClient(networkManager, true); - } - - // Shutdown and clean up the server NetworkManager instance - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].Clear(); - yield return StopOneClient(m_ServerNetworkManager); - - // Set the prefabs to active again - foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) - { - networkPrefab.Prefab.SetActive(true); - } - - // Disable scene management and start the host - m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = false; - m_ServerNetworkManager.StartHost(); - yield return s_DefaultWaitForTick; - - // Create 2 new clients and connect them - for (int i = 0; i < NumberOfClients; i++) - { - yield return CreateAndStartNewClient(); - } - } - - m_ObserverTestType = observerTestTypes; - var prefabNetworkObject = m_ObserverPrefab.GetComponent(); - prefabNetworkObject.SpawnWithObservers = observerTestTypes == ObserverTestTypes.WithObservers; - var instance = SpawnObject(m_ObserverPrefab, m_ServerNetworkManager); - m_ObserverTestNetworkObject = instance.GetComponent(); - var withoutObservers = m_ObserverTestType == ObserverTestTypes.WithoutObservers; - if (withoutObservers) - { - // Just give a little time to make sure nothing spawned - yield return s_DefaultWaitForTick; - } - yield return WaitForConditionOrTimeOut(CheckClientsSideObserverTestObj); - AssertOnTimeout($"{(withoutObservers ? k_WithoutObserversError : k_WithObserversError)} {k_ObserverTestObjName} object!"); - // If we spawned without observers - if (withoutObservers) - { - // Make each client an observer - foreach (var client in m_ClientNetworkManagers) - { - m_ObserverTestNetworkObject.NetworkShow(client.LocalClientId); - } - - // Validate the clients spawned the NetworkObject - m_ObserverTestType = ObserverTestTypes.WithObservers; - yield return WaitForConditionOrTimeOut(CheckClientsSideObserverTestObj); - AssertOnTimeout($"{k_WithObserversError} {k_ObserverTestObjName} object!"); - - // Validate that a late joining client does not see the NetworkObject when it spawns - yield return CreateAndStartNewClient(); - - m_ObserverTestType = ObserverTestTypes.WithoutObservers; - // Just give a little time to make sure nothing spawned - yield return s_DefaultWaitForTick; - - // This just requires a targeted check to assure the newly joined client did not spawn the NetworkObject with SpawnWithObservers set to false - var lateJoinClientId = m_ClientNetworkManagers[m_ClientNetworkManagers.Length - 1].LocalClientId; - Assert.False(s_GlobalNetworkObjects.ContainsKey(lateJoinClientId), $"[Client-{lateJoinClientId}] Spawned {instance.name} when it shouldn't have!"); - - // Now validate that we can make the NetworkObject visible to the newly joined client - m_ObserverTestNetworkObject.NetworkShow(m_ClientNetworkManagers[NumberOfClients].LocalClientId); - - // Validate the NetworkObject is visible to all connected clients (including the recently joined client) - m_ObserverTestType = ObserverTestTypes.WithObservers; - yield return WaitForConditionOrTimeOut(CheckClientsSideObserverTestObj); - AssertOnTimeout($"{k_WithObserversError} {k_ObserverTestObjName} object!"); - } - } - - /// - /// Tests that instantiating a and destroying without spawning it - /// does not run or . - /// - [UnityTest] - public IEnumerator InstantiateDestroySpawnNotCalled() - { - m_TestNetworkObjectPrefab = new GameObject("InstantiateDestroySpawnNotCalled_Object"); - var networkObject = m_TestNetworkObjectPrefab.AddComponent(); - var fail = m_TestNetworkObjectPrefab.AddComponent(); - - // instantiate - m_TestNetworkObjectInstance = Object.Instantiate(m_TestNetworkObjectPrefab); - yield return null; - Object.Destroy(m_TestNetworkObjectInstance); - - } - - private class FailWhenSpawned : NetworkBehaviour - { - public override void OnNetworkSpawn() - { - Assert.Fail("Spawn should not be called on not spawned object"); - } - - public override void OnNetworkDespawn() - { - Assert.Fail("Depawn should not be called on not spawned object"); - } - } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - protected override IEnumerator OnTearDown() - { - if (m_ObserverPrefab != null) - { - Object.Destroy(m_ObserverPrefab); - } - - if (m_TestNetworkObjectPrefab != null) - { - Object.Destroy(m_TestNetworkObjectPrefab); - } - - if (m_TestNetworkObjectInstance != null) - { - Object.Destroy(m_TestNetworkObjectInstance); - } - yield return base.OnTearDown(); - } - - private List m_ClientTrackOnSpawnInstances = new List(); - - /// - /// Test that callbacks are run for playerobject spawn, despawn, regular spawn, destroy on server. - /// - /// - [UnityTest] - public IEnumerator TestOnNetworkSpawnCallbacks() - { - // [Host-Side] Get the Host owned instance - var serverInstance = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ServerNetworkManager.LocalClientId].GetComponent(); - - foreach (var client in m_ClientNetworkManagers) - { - var clientRpcTests = m_PlayerNetworkObjects[client.LocalClientId][m_ServerNetworkManager.LocalClientId].gameObject.GetComponent(); - Assert.IsNotNull(clientRpcTests); - m_ClientTrackOnSpawnInstances.Add(clientRpcTests); - } - - // -------------- step 1 check player spawn despawn - - // check spawned on server - Assert.AreEqual(1, serverInstance.OnNetworkSpawnCalledCount); - - // safety check server despawned - Assert.AreEqual(0, serverInstance.OnNetworkDespawnCalledCount); - - // Conditional check for clients spawning or despawning - var checkSpawnCondition = false; - var expectedSpawnCount = 1; - var expectedDespawnCount = 0; - bool HasConditionBeenMet() - { - var clientsCompleted = 0; - // check spawned on client - foreach (var clientInstance in m_ClientTrackOnSpawnInstances) - { - if (checkSpawnCondition) - { - if (clientInstance.OnNetworkSpawnCalledCount == expectedSpawnCount) - { - clientsCompleted++; - } - } - else - { - if (clientInstance.OnNetworkDespawnCalledCount == expectedDespawnCount) - { - clientsCompleted++; - } - } - } - return clientsCompleted >= NumberOfClients; - } - - // safety check that all clients have not been despawned yet - Assert.True(HasConditionBeenMet(), "Failed condition that all clients not despawned yet!"); - - // now verify that all clients have been spawned - checkSpawnCondition = true; - yield return WaitForConditionOrTimeOut(HasConditionBeenMet); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side spawns!"); - - // despawn on server. However, since we'll be using this object later in the test, don't delete it - serverInstance.GetComponent().Despawn(false); - - // check despawned on server - Assert.AreEqual(1, serverInstance.OnNetworkDespawnCalledCount); - // we now expect the clients to each have despawned once - expectedDespawnCount = 1; - - yield return s_DefaultWaitForTick; - // verify that all client-side instances are despawned - checkSpawnCondition = false; - yield return WaitForConditionOrTimeOut(HasConditionBeenMet); - - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side despawns!"); - - //----------- step 2 check spawn and destroy again - serverInstance.GetComponent().Spawn(); - // wait a tick - yield return s_DefaultWaitForTick; - // check spawned again on server this is 2 because we are reusing the object which was already spawned once. - Assert.AreEqual(2, serverInstance.OnNetworkSpawnCalledCount); - - checkSpawnCondition = true; - yield return WaitForConditionOrTimeOut(HasConditionBeenMet); - - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side spawns! (2nd pass)"); - - // destroy the server object - Object.Destroy(serverInstance.gameObject); - - yield return s_DefaultWaitForTick; - - // check whether despawned was called again on server instance - Assert.AreEqual(2, serverInstance.OnNetworkDespawnCalledCount); - - checkSpawnCondition = false; - yield return WaitForConditionOrTimeOut(HasConditionBeenMet); - - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out while waiting for client side despawns! (2nd pass)"); - } - - [Test] - public void DynamicallySpawnedNoSceneOriginException() - { - var gameObject = new GameObject(); - var networkObject = gameObject.AddComponent(); - networkObject.IsSpawned = true; - networkObject.SceneOriginHandle = 0; - networkObject.IsSceneObject = false; - // This validates invoking GetSceneOriginHandle will not throw an exception for a dynamically spawned NetworkObject - // when the scene of origin handle is zero - var sceneOriginHandle = networkObject.GetSceneOriginHandle(); - - // This validates that GetSceneOriginHandle will return the GameObject's scene handle that should be the currently active scene - var activeSceneHandle = UnityEngine.SceneManagement.SceneManager.GetActiveScene().handle; - Assert.IsTrue(sceneOriginHandle == activeSceneHandle, $"{nameof(NetworkObject)} should have returned the active scene handle of {activeSceneHandle} but returned {sceneOriginHandle}"); - } - - private class TrackOnSpawnFunctions : NetworkBehaviour - { - public int OnNetworkSpawnCalledCount { get; private set; } - public int OnNetworkDespawnCalledCount { get; private set; } - - public override void OnNetworkSpawn() - { - OnNetworkSpawnCalledCount++; - } - - public override void OnNetworkDespawn() - { - OnNetworkDespawnCalledCount++; - } - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs.meta deleted file mode 100644 index 407ad63..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dbb32425abaa21a44aeacf00f37ca4e2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs deleted file mode 100644 index 6ae761b..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System.Collections; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(NetworkTopologyTypes.ClientServer)] - internal class NetworkObjectOwnershipPropertiesTests : NetcodeIntegrationTest - { - private class DummyNetworkBehaviour : NetworkBehaviour - { - - } - - protected override int NumberOfClients => 2; - private GameObject m_PrefabToSpawn; - private NetworkObject m_OwnerSpawnedInstance; - private NetworkObject m_TargetOwnerInstance; - private NetworkManager m_InitialOwner; - private NetworkManager m_NextTargetOwner; - - private ulong m_InitialOwnerId; - private ulong m_TargetOwnerId; - private bool m_SpawnedInstanceIsOwner; - private bool m_InitialOwnerOwnedBySever; - private bool m_TargetOwnerOwnedBySever; - - public NetworkObjectOwnershipPropertiesTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - - protected override IEnumerator OnTearDown() - { - m_OwnerSpawnedInstance = null; - m_InitialOwner = null; - m_NextTargetOwner = null; - m_PrefabToSpawn = null; - return base.OnTearDown(); - } - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("ClientOwnedObject"); - m_PrefabToSpawn.gameObject.AddComponent(); - m_PrefabToSpawn.GetComponent().SetOwnershipStatus(NetworkObject.OwnershipStatus.Distributable); - } - - public enum InstanceTypes - { - Server, - Client - } - - private StringBuilder m_OwnershipPropagatedFailures = new StringBuilder(); - private bool OwnershipPropagated() - { - var conditionMet = true; - m_OwnershipPropagatedFailures.Clear(); - // In distributed authority mode, we will check client owner to DAHost owner with InstanceTypes.Server and client owner to client - // when InstanceTypes.Client - if (m_DistributedAuthority) - { - if (!m_ClientNetworkManagers[1].SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId)) - { - conditionMet = false; - m_OwnershipPropagatedFailures.AppendLine($"Client-{m_ClientNetworkManagers[1].LocalClientId} has no ownership entry for {m_OwnerSpawnedInstance.name} ({m_OwnerSpawnedInstance.NetworkObjectId})"); - } - if (!m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId)) - { - conditionMet = false; - m_OwnershipPropagatedFailures.AppendLine($"Client-{m_ClientNetworkManagers[0].LocalClientId} has no ownership entry for {m_OwnerSpawnedInstance.name} ({m_OwnerSpawnedInstance.NetworkObjectId})"); - } - if (!m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId)) - { - conditionMet = false; - m_OwnershipPropagatedFailures.AppendLine($"Client-{m_ServerNetworkManager.LocalClientId} has no ownership entry for {m_OwnerSpawnedInstance.name} ({m_OwnerSpawnedInstance.NetworkObjectId})"); - } - } - else - { - if (m_NextTargetOwner != m_ServerNetworkManager) - { - if (!m_NextTargetOwner.SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId)) - { - conditionMet = false; - m_OwnershipPropagatedFailures.AppendLine($"Client-{m_NextTargetOwner.LocalClientId} has no ownership entry for {m_OwnerSpawnedInstance.name} ({m_OwnerSpawnedInstance.NetworkObjectId})"); - } - } - if (!m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId)) - { - conditionMet = false; - m_OwnershipPropagatedFailures.AppendLine($"Client-{m_ServerNetworkManager.LocalClientId} has no ownership entry for {m_OwnerSpawnedInstance.name} ({m_OwnerSpawnedInstance.NetworkObjectId})"); - } - } - return conditionMet; - } - - private void ValidateOwnerShipProperties(bool targetIsOwner = false) - { - Assert.AreEqual(m_OwnerSpawnedInstance.IsOwner, m_SpawnedInstanceIsOwner); - Assert.AreEqual(m_OwnerSpawnedInstance.IsOwnedByServer, m_InitialOwnerOwnedBySever); - Assert.AreEqual(targetIsOwner ? m_TargetOwnerId : m_InitialOwnerId, m_OwnerSpawnedInstance.OwnerClientId); - - var initialOwnerBehaviour = m_OwnerSpawnedInstance.GetComponent(); - Assert.AreEqual(initialOwnerBehaviour.IsOwner, m_SpawnedInstanceIsOwner); - Assert.AreEqual(initialOwnerBehaviour.IsOwnedByServer, m_InitialOwnerOwnedBySever); - Assert.AreEqual(targetIsOwner ? m_TargetOwnerId : m_InitialOwnerId, initialOwnerBehaviour.OwnerClientId); - - Assert.AreEqual(m_TargetOwnerInstance.IsOwner, targetIsOwner); - Assert.AreEqual(m_TargetOwnerInstance.IsOwnedByServer, m_TargetOwnerOwnedBySever); - - Assert.AreEqual(targetIsOwner ? m_TargetOwnerId : m_InitialOwnerId, m_TargetOwnerInstance.OwnerClientId); - var targetOwnerBehaviour = m_TargetOwnerInstance.GetComponent(); - Assert.AreEqual(targetOwnerBehaviour.IsOwner, targetIsOwner); - Assert.AreEqual(targetOwnerBehaviour.IsOwnedByServer, m_TargetOwnerOwnedBySever); - Assert.AreEqual(targetIsOwner ? m_TargetOwnerId : m_InitialOwnerId, m_TargetOwnerInstance.OwnerClientId); - } - - - [UnityTest] - public IEnumerator ValidatePropertiesWithOwnershipChanges([Values(InstanceTypes.Server, InstanceTypes.Client)] InstanceTypes instanceType) - { - m_NextTargetOwner = instanceType == InstanceTypes.Server ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - m_InitialOwner = instanceType == InstanceTypes.Client ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - - // In distributed authority mode, we will check client owner to DAHost owner with InstanceTypes.Server and client owner to client - // when InstanceTypes.Client - if (m_DistributedAuthority) - { - m_InitialOwner = m_ClientNetworkManagers[0]; - if (instanceType == InstanceTypes.Client) - { - m_NextTargetOwner = m_ClientNetworkManagers[1]; - } - m_PrefabToSpawn.GetComponent().SetOwnershipStatus(NetworkObject.OwnershipStatus.Transferable); - } - - m_InitialOwnerId = m_InitialOwner.LocalClientId; - m_TargetOwnerId = m_NextTargetOwner.LocalClientId; - m_InitialOwnerOwnedBySever = m_InitialOwner.IsServer; - m_TargetOwnerOwnedBySever = m_InitialOwner.IsServer; - var objectInstance = SpawnObject(m_PrefabToSpawn, m_InitialOwner); - - m_OwnerSpawnedInstance = objectInstance.GetComponent(); - m_SpawnedInstanceIsOwner = m_OwnerSpawnedInstance.NetworkManager == m_InitialOwner; - // Sanity check to verify that the next owner to target is not the owner of the spawned object - var hasEntry = m_InitialOwner.SpawnManager.GetClientOwnedObjects(m_NextTargetOwner.LocalClientId).Any(x => x.NetworkObjectId == m_OwnerSpawnedInstance.NetworkObjectId); - Assert.False(hasEntry); - - // Since CreateObjectMessage gets proxied by DAHost, just wait until the next target owner has the spawned instance in the s_GlobalNetworkObjects table. - yield return WaitForConditionOrTimeOut(() => s_GlobalNetworkObjects.ContainsKey(m_NextTargetOwner.LocalClientId) && s_GlobalNetworkObjects[m_NextTargetOwner.LocalClientId].ContainsKey(m_OwnerSpawnedInstance.NetworkObjectId)); - AssertOnTimeout($"Timed out waiting for Client-{m_NextTargetOwner.LocalClientId} to have an instance entry of {m_OwnerSpawnedInstance.name}-{m_OwnerSpawnedInstance.NetworkObjectId}!"); - - // Get the target client's instance of the spawned object - m_TargetOwnerInstance = s_GlobalNetworkObjects[m_NextTargetOwner.LocalClientId][m_OwnerSpawnedInstance.NetworkObjectId]; - - // Validate that NetworkObject and NetworkBehaviour ownership properties are correct - ValidateOwnerShipProperties(); - - // The authority always changes the ownership - // Client-Server: It will always be the host instance - // Distributed Authority: It can be either the DAHost or the client - if (m_DistributedAuthority) - { - // Use the target client's instance to change ownership - m_TargetOwnerInstance.ChangeOwnership(m_NextTargetOwner.LocalClientId); - if (instanceType == InstanceTypes.Client) - { - var networkManagersList = new System.Collections.Generic.List() { m_ServerNetworkManager, m_ClientNetworkManagers[0] }; - // Provide enough time for the client to receive and process the spawned message. - yield return WaitForMessageReceived(networkManagersList); - } - else - { - // Provide enough time for the client to receive and process the change in ownership message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - } - } - else - { - m_OwnerSpawnedInstance.ChangeOwnership(m_NextTargetOwner.LocalClientId); - // Provide enough time for the client to receive and process the change in ownership message. - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - } - - // Ensure it's the ownership tables are updated - yield return WaitForConditionOrTimeOut(OwnershipPropagated); - AssertOnTimeout($"Timed out waiting for ownership to propagate!\n{m_OwnershipPropagatedFailures}"); - - m_SpawnedInstanceIsOwner = m_OwnerSpawnedInstance.NetworkManager == m_NextTargetOwner; - if (m_SpawnedInstanceIsOwner) - { - m_InitialOwnerOwnedBySever = m_OwnerSpawnedInstance.NetworkManager.IsServer; - } - m_InitialOwnerOwnedBySever = m_NextTargetOwner.IsServer; - m_TargetOwnerOwnedBySever = m_NextTargetOwner.IsServer; - - // Validate that NetworkObject and NetworkBehaviour ownership properties are correct - ValidateOwnerShipProperties(true); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs.meta deleted file mode 100644 index 5a555c0..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipPropertiesTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7c88cc36139c1574fba571485477d642 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs deleted file mode 100644 index bda9d15..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs +++ /dev/null @@ -1,462 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkObjectOwnershipComponent : NetworkBehaviour - { - public static Dictionary SpawnedInstances = new Dictionary(); - - public bool OnLostOwnershipFired = false; - public bool OnGainedOwnershipFired = false; - - public override void OnLostOwnership() - { - OnLostOwnershipFired = true; - } - - public override void OnGainedOwnership() - { - OnGainedOwnershipFired = true; - } - - public override void OnNetworkSpawn() - { - if (!SpawnedInstances.ContainsKey(NetworkManager.LocalClientId)) - { - SpawnedInstances.Add(NetworkManager.LocalClientId, this); - } - base.OnNetworkSpawn(); - } - - public void ResetFlags() - { - OnLostOwnershipFired = false; - OnGainedOwnershipFired = false; - } - } - - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class NetworkObjectOwnershipTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 9; - - private GameObject m_OwnershipPrefab; - private GameObject m_OwnershipObject; - private NetworkObject m_OwnershipNetworkObject; - - public NetworkObjectOwnershipTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - public enum OwnershipChecks - { - Change, - Remove - } - - protected override IEnumerator OnSetup() - { - NetworkObjectOwnershipComponent.SpawnedInstances.Clear(); - return base.OnSetup(); - } - - protected override void OnServerAndClientsCreated() - { - m_OwnershipPrefab = CreateNetworkObjectPrefab("OnwershipPrefab"); - m_OwnershipPrefab.AddComponent(); - if (m_DistributedAuthority) - { - m_OwnershipPrefab.GetComponent().SetOwnershipStatus(NetworkObject.OwnershipStatus.Transferable); - } - base.OnServerAndClientsCreated(); - } - - [Test] - public void TestPlayerIsOwned() - { - var clientOwnedObjects = m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId); - - var clientPlayerObject = clientOwnedObjects.Where((c) => c.IsLocalPlayer).FirstOrDefault(); - Assert.NotNull(clientPlayerObject, $"Client Id {m_ClientNetworkManagers[0].LocalClientId} does not have its local player marked as an owned object!"); - - clientPlayerObject = m_ClientNetworkManagers[0].LocalClient.OwnedObjects.Where((c) => c.IsLocalPlayer).FirstOrDefault(); - Assert.NotNull(clientPlayerObject, $"Client Id {m_ClientNetworkManagers[0].LocalClientId} does not have its local player marked as an owned object using local client!"); - } - - private bool AllObjectsSpawnedOnClients() - { - if (!NetworkObjectOwnershipComponent.SpawnedInstances.ContainsKey(m_ServerNetworkManager.LocalClientId)) - { - return false; - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!NetworkObjectOwnershipComponent.SpawnedInstances.ContainsKey(client.LocalClientId)) - { - return false; - } - } - return true; - } - - [UnityTest] - public IEnumerator TestOwnershipCallbacks([Values] OwnershipChecks ownershipChecks) - { - m_OwnershipObject = SpawnObject(m_OwnershipPrefab, m_ServerNetworkManager); - m_OwnershipNetworkObject = m_OwnershipObject.GetComponent(); - - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeHandled(m_ClientNetworkManagers[0]); - - yield return WaitForConditionOrTimeOut(AllObjectsSpawnedOnClients); - AssertOnTimeout($"Timed out waiting for all clients to spawn the ownership object!"); - - var ownershipNetworkObjectId = m_OwnershipNetworkObject.NetworkObjectId; - Assert.That(ownershipNetworkObjectId, Is.GreaterThan(0)); - Assert.That(m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId)); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - Assert.That(clientNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId)); - } - - // Verifies that removing the ownership when the default (server) is already set does not cause a Key Not Found Exception - m_ServerNetworkManager.SpawnManager.RemoveOwnership(m_OwnershipNetworkObject); - - var serverObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[ownershipNetworkObjectId]; - var clientObject = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[ownershipNetworkObjectId]; - Assert.That(serverObject, Is.Not.Null); - Assert.That(clientObject, Is.Not.Null); - - var serverComponent = serverObject.GetComponent(); - var clientComponent = clientObject.GetComponent(); - Assert.That(serverComponent, Is.Not.Null); - Assert.That(clientComponent, Is.Not.Null); - - Assert.That(serverObject.OwnerClientId, Is.EqualTo(NetworkManager.ServerClientId)); - Assert.That(clientObject.OwnerClientId, Is.EqualTo(NetworkManager.ServerClientId)); - - Assert.That(m_ServerNetworkManager.ConnectedClients.ContainsKey(m_ClientNetworkManagers[0].LocalClientId)); - - serverObject.ChangeOwnership(clientComponent.NetworkManager.LocalClientId); - yield return s_DefaultWaitForTick; - - Assert.That(serverComponent.OnLostOwnershipFired); - Assert.That(serverComponent.OwnerClientId, Is.EqualTo(m_ClientNetworkManagers[0].LocalClientId)); - - yield return WaitForConditionOrTimeOut(() => clientComponent.OnGainedOwnershipFired); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to gain ownership!"); - Assert.That(clientComponent.OnGainedOwnershipFired); - Assert.That(clientComponent.OwnerClientId, Is.EqualTo(m_ClientNetworkManagers[0].LocalClientId)); - - serverComponent.ResetFlags(); - clientComponent.ResetFlags(); - - if (ownershipChecks == OwnershipChecks.Change) - { - // Validates that when ownership is changed back to the server it will get an OnGainedOwnership notification - serverObject.ChangeOwnership(NetworkManager.ServerClientId); - } - else - { - // Validates that when ownership is removed the server gets an OnGainedOwnership notification - // In distributed authority mode, the current owner just rolls the ownership back over to the DAHost client (i.e. host mocking CMB Service) - if (m_DistributedAuthority) - { - clientObject.ChangeOwnership(NetworkManager.ServerClientId); - } - else - { - serverObject.RemoveOwnership(); - } - } - - yield return WaitForConditionOrTimeOut(() => serverComponent.OnGainedOwnershipFired && serverComponent.OwnerClientId == m_ServerNetworkManager.LocalClientId); - AssertOnTimeout($"Timed out waiting for ownership to be transfered back to the host instance!"); - - yield return WaitForConditionOrTimeOut(() => clientComponent.OnLostOwnershipFired && clientComponent.OwnerClientId == m_ServerNetworkManager.LocalClientId); - AssertOnTimeout($"Timed out waiting for client-side lose ownership event to trigger or owner identifier to be equal to the host!"); - } - - /// - /// Verifies that switching ownership between several clients works properly - /// - [UnityTest] - public IEnumerator TestOwnershipCallbacksSeveralClients([Values] OwnershipChecks ownershipChecks) - { - // Build our message hook entries tables so we can determine if all clients received spawn or ownership messages - var messageHookEntriesForSpawn = new List(); - var messageHookEntriesForOwnership = new List(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var messageHook = new MessageHookEntry(clientNetworkManager); - messageHook.AssignMessageType(); - messageHookEntriesForSpawn.Add(messageHook); - messageHook = new MessageHookEntry(clientNetworkManager); - messageHook.AssignMessageType(); - messageHookEntriesForOwnership.Add(messageHook); - } - // Used to determine if all clients received the CreateObjectMessage - var spawnMessageHooks = new MessageHooksConditional(messageHookEntriesForSpawn); - - // Used to determine if all clients received the ChangeOwnershipMessage - var ownershipMessageHooks = new MessageHooksConditional(messageHookEntriesForOwnership); - - // Spawn our test object from server with server ownership - m_OwnershipObject = SpawnObject(m_OwnershipPrefab, m_ServerNetworkManager); - m_OwnershipNetworkObject = m_OwnershipObject.GetComponent(); - - // Wait for all clients to receive the CreateObjectMessage - yield return WaitForConditionOrTimeOut(spawnMessageHooks); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all clients to receive the {nameof(CreateObjectMessage)} message."); - - // Validate the NetworkObjectId and that the server and all clients have this NetworkObject - var ownershipNetworkObjectId = m_OwnershipNetworkObject.NetworkObjectId; - Assert.That(ownershipNetworkObjectId, Is.GreaterThan(0)); - Assert.That(m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId)); - - bool WaitForClientsToSpawnNetworkObject() - { - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (!clientNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(ownershipNetworkObjectId)) - { - return false; - } - } - return true; - } - - yield return WaitForConditionOrTimeOut(WaitForClientsToSpawnNetworkObject); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for all clients to change ownership!"); - - // Verifies that removing the ownership when the default (server) is already set does not cause a Key Not Found Exception - m_ServerNetworkManager.SpawnManager.RemoveOwnership(m_OwnershipNetworkObject); - var serverObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[ownershipNetworkObjectId]; - Assert.That(serverObject, Is.Not.Null); - var clientObject = (NetworkObject)null; - var clientObjects = new List(); - for (int i = 0; i < NumberOfClients; i++) - { - clientObject = m_ClientNetworkManagers[i].SpawnManager.SpawnedObjects[ownershipNetworkObjectId]; - Assert.That(clientObject, Is.Not.Null); - clientObjects.Add(clientObject); - } - - // Verify the server side component - var serverComponent = serverObject.GetComponent(); - Assert.That(serverComponent, Is.Not.Null); - Assert.That(serverObject.OwnerClientId, Is.EqualTo(NetworkManager.ServerClientId)); - - // Verify the clients components - for (int i = 0; i < NumberOfClients; i++) - { - var clientComponent = clientObjects[i].GetComponent(); - Assert.That(clientComponent.OwnerClientId, Is.EqualTo(NetworkManager.ServerClientId)); - clientComponent.ResetFlags(); - } - - // After the 1st client has been given ownership to the object, this will be used to make sure each previous owner properly received the remove ownership message - var previousClientComponent = (NetworkObjectOwnershipComponent)null; - - var networkManagersDAMode = new List(); - - for (int clientIndex = 0; clientIndex < NumberOfClients; clientIndex++) - { - clientObject = clientObjects[clientIndex]; - var clientId = m_ClientNetworkManagers[clientIndex].LocalClientId; - - Assert.That(m_ServerNetworkManager.ConnectedClients.ContainsKey(clientId)); - serverObject.ChangeOwnership(clientId); - yield return s_DefaultWaitForTick; - Assert.That(serverComponent.OnLostOwnershipFired); - Assert.That(serverComponent.OwnerClientId, Is.EqualTo(clientId)); - // Wait for all clients to receive the CreateObjectMessage - yield return WaitForConditionOrTimeOut(ownershipMessageHooks); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all clients to receive the {nameof(ChangeOwnershipMessage)} message."); - - var previousNetworkManager = m_ServerNetworkManager; - if (previousClientComponent != null) - { - // Once we have a previousClientComponent, we want to verify the server is keeping track for the removal of ownership in the OwnershipToObjectsTable - Assert.That(!m_ServerNetworkManager.SpawnManager.OwnershipToObjectsTable[m_ServerNetworkManager.LocalClientId].ContainsKey(serverObject.NetworkObjectId)); - previousNetworkManager = previousClientComponent.NetworkManager; - Assert.That(previousClientComponent.OnLostOwnershipFired); - Assert.That(previousClientComponent.OwnerClientId, Is.EqualTo(clientId)); - } - - // Assure the previous owner is no longer in the local table of the previous owner. - Assert.That(!previousNetworkManager.SpawnManager.OwnershipToObjectsTable[previousNetworkManager.LocalClientId].ContainsKey(serverObject.NetworkObjectId)); - - var currentClientComponent = clientObjects[clientIndex].GetComponent(); - Assert.That(currentClientComponent.OnGainedOwnershipFired); - - // Possibly the more important part of this test: - // Check to make sure all other non-former or current ownership clients are synchronized to each ownership change - for (int i = 0; i < NumberOfClients; i++) - { - var clientComponent = clientObjects[i].GetComponent(); - Assert.That(clientComponent, Is.Not.Null); - Assert.That(clientComponent.OwnerClientId, Is.EqualTo(clientId)); - clientComponent.ResetFlags(); - } - // We must reset this for each iteration in order to make sure all clients receive the ChangeOwnershipMessage - ownershipMessageHooks.Reset(); - - // Set the current owner client to the previous one - previousClientComponent = currentClientComponent; - } - - if (ownershipChecks == OwnershipChecks.Change) - { - // Validates that when ownership is changed back to the server it will get an OnGainedOwnership notification - serverObject.ChangeOwnership(NetworkManager.ServerClientId); - } - else - { - // Validates that when ownership is removed the server gets an OnGainedOwnership notification - // In distributed authority mode, the current owner just rolls the ownership back over to the DAHost client (i.e. host mocking CMB Service) - if (m_DistributedAuthority) - { - // In distributed authority, we have to clear out the NetworkManager instances as this changes relative to authority. - networkManagersDAMode.Clear(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (clientNetworkManager.LocalClientId == clientObject.OwnerClientId) - { - continue; - } - networkManagersDAMode.Add(clientNetworkManager); - } - - if (!UseCMBService() && clientObject.OwnerClientId != m_ServerNetworkManager.LocalClientId) - { - networkManagersDAMode.Add(m_ServerNetworkManager); - } - clientObject.ChangeOwnership(NetworkManager.ServerClientId); - } - else - { - serverObject.RemoveOwnership(); - } - } - - if (m_DistributedAuthority) - { - // We use an alternate method (other than message hooks) to verify each client received the ownership message since message hooks becomes problematic when you need - // to make dynamic changes to your targets. - yield return WaitForConditionOrTimeOut(() => OwnershipChangedOnAllTargetedClients(networkManagersDAMode, clientObject.NetworkObjectId, NetworkManager.ServerClientId)); - } - else - { - yield return WaitForConditionOrTimeOut(ownershipMessageHooks); - } - - - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for all clients to receive the {nameof(ChangeOwnershipMessage)} message (back to server)."); - - Assert.That(serverComponent.OnGainedOwnershipFired); - Assert.That(serverComponent.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId)); - - yield return WaitForConditionOrTimeOut(() => previousClientComponent.OnLostOwnershipFired); - - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {previousClientComponent.name} to lose ownership!"); - - // Make sure all client-side versions of the object is once again owned by the server - for (int i = 0; i < NumberOfClients; i++) - { - var clientComponent = clientObjects[i].GetComponent(); - Assert.That(clientComponent, Is.Not.Null); - Assert.That(clientComponent.OwnerClientId, Is.EqualTo(m_ServerNetworkManager.LocalClientId)); - clientComponent.ResetFlags(); - } - serverComponent.ResetFlags(); - } - - private bool OwnershipChangedOnAllTargetedClients(List networkManagers, ulong networkObjectId, ulong expectedOwner) - { - foreach (var networkManager in networkManagers) - { - if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) - { - return false; - } - if (networkManager.SpawnManager.SpawnedObjects[networkObjectId].OwnerClientId != expectedOwner) - { - return false; - } - } - return true; - } - - private const int k_NumberOfSpawnedObjects = 5; - - private bool AllClientsHaveCorrectObjectCount() - { - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (clientNetworkManager.LocalClient.OwnedObjects.Length < k_NumberOfSpawnedObjects) - { - return false; - } - } - - return true; - } - - private bool ServerHasCorrectClientOwnedObjectCount() - { - // Only check when we are the host - if (m_ServerNetworkManager.IsHost) - { - if (m_ServerNetworkManager.LocalClient.OwnedObjects.Length < k_NumberOfSpawnedObjects) - { - return false; - } - } - - foreach (var connectedClient in m_ServerNetworkManager.ConnectedClients) - { - if (connectedClient.Value.OwnedObjects.Length < k_NumberOfSpawnedObjects) - { - return false; - } - } - return true; - } - - [UnityTest] - public IEnumerator TestOwnedObjectCounts() - { - if (m_ServerNetworkManager.IsHost) - { - for (int i = 0; i < 5; i++) - { - SpawnObject(m_OwnershipPrefab, m_ServerNetworkManager); - } - } - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - for (int i = 0; i < 5; i++) - { - SpawnObject(m_OwnershipPrefab, clientNetworkManager); - } - } - - yield return WaitForConditionOrTimeOut(AllClientsHaveCorrectObjectCount); - AssertOnTimeout($"Not all clients spawned {k_NumberOfSpawnedObjects} {nameof(NetworkObject)}s!"); - - yield return WaitForConditionOrTimeOut(ServerHasCorrectClientOwnedObjectCount); - AssertOnTimeout($"Server does not have the correct count for all clients spawned {k_NumberOfSpawnedObjects} {nameof(NetworkObject)}s!"); - - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs.meta deleted file mode 100644 index d8dea9e..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectOwnershipTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 08f9390096acb44698be8b3eacf242ea -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs deleted file mode 100644 index f1557f4..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Tests properties of NetworkObject for proper functionality. - /// - internal class NetworkObjectPropertyTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - private NetworkObject m_TestPrefabNetworkObject; - - protected override void OnServerAndClientsCreated() - { - // create prefab and get the NetworkObject component attached to it - m_TestPrefabNetworkObject = CreateNetworkObjectPrefab("TestObject").GetComponent(); - } - - /// - /// Tests PrefabHashId returns correctly when the NetworkObject is not a prefab. - /// - [Test] - public void TestPrefabHashIdPropertyNotAPrefab() - { - const uint kInvalidPrefabHashId = 0; - - var gameObject = new GameObject("TestObject"); - var networkObject = gameObject.AddComponent(); - Assert.AreEqual(kInvalidPrefabHashId, networkObject.PrefabIdHash); - } - - /// - /// Tests PrefabHashId returns correctly when the NetworkObject is a prefab. - /// - /// - [Test] - public void TestPrefabHashIdPropertyIsAPrefab() - { - Assert.AreEqual(m_TestPrefabNetworkObject.GlobalObjectIdHash, m_TestPrefabNetworkObject.PrefabIdHash); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs.meta deleted file mode 100644 index 7442554..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectPropertyTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c11415470078c1846836b9a8b6f80dc2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs deleted file mode 100644 index b80e055..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - - [TestFixture(NetworkTopologyTypes.ClientServer)] - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - internal class NetworkObjectSpawnManyObjectsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - private const int k_SpawnedObjects = 1500; - - private NetworkPrefab m_PrefabToSpawn; - - public NetworkObjectSpawnManyObjectsTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - // Using this component assures we will know precisely how many prefabs were spawned on the client - internal class SpawnObjecTrackingComponent : NetworkBehaviour - { - public static int SpawnedObjects; - public override void OnNetworkSpawn() - { - if (!IsServer) - { - SpawnedObjects++; - } - } - } - - protected override void OnServerAndClientsCreated() - { - SpawnObjecTrackingComponent.SpawnedObjects = 0; - // create prefab - var gameObject = new GameObject("TestObject"); - var networkObject = gameObject.AddComponent(); - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject); - networkObject.IsSceneObject = false; - gameObject.AddComponent(); - - m_PrefabToSpawn = new NetworkPrefab() { Prefab = gameObject }; - - m_ServerNetworkManager.NetworkConfig.Prefabs.Add(m_PrefabToSpawn); - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.Prefabs.Add(m_PrefabToSpawn); - } - } - - [UnityTest] - public IEnumerator WhenManyObjectsAreSpawnedAtOnce_AllAreReceived() - { - var timeStarted = Time.realtimeSinceStartup; - for (int x = 0; x < k_SpawnedObjects; x++) - { - NetworkObject serverObject = Object.Instantiate(m_PrefabToSpawn.Prefab).GetComponent(); - serverObject.NetworkManagerOwner = m_ServerNetworkManager; - serverObject.Spawn(); - } - - var timeSpawned = Time.realtimeSinceStartup - timeStarted; - // Provide plenty of time to spawn all 1500 objects in case the CI VM is running slow - var timeoutHelper = new TimeoutHelper(30); - // ensure all objects are replicated - yield return WaitForConditionOrTimeOut(() => SpawnObjecTrackingComponent.SpawnedObjects == k_SpawnedObjects, timeoutHelper); - - AssertOnTimeout($"Timed out waiting for the client to spawn {k_SpawnedObjects} objects! Time to spawn: {timeSpawned} | Time to timeout: {timeStarted - Time.realtimeSinceStartup}", timeoutHelper); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs.meta deleted file mode 100644 index a62cd5a..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4e0439aa2d2a72e4aa42b051d26af366 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs b/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs deleted file mode 100644 index c4714d7..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs +++ /dev/null @@ -1,701 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - -namespace Unity.Netcode.RuntimeTests -{ - - [TestFixture(VariableLengthSafety.DisableNetVarSafety, HostOrServer.DAHost)] - [TestFixture(VariableLengthSafety.DisableNetVarSafety, HostOrServer.Host)] - [TestFixture(VariableLengthSafety.EnabledNetVarSafety, HostOrServer.Host)] - [TestFixture(VariableLengthSafety.DisableNetVarSafety, HostOrServer.Server)] - [TestFixture(VariableLengthSafety.EnabledNetVarSafety, HostOrServer.Server)] - internal class NetworkObjectSynchronizationTests : NetcodeIntegrationTest - { - private const int k_NumberToSpawn = 30; - protected override int NumberOfClients => 0; - - private GameObject m_NetworkPrefab; - private GameObject m_InValidNetworkPrefab; - private GameObject m_SynchronizationPrefab; - private GameObject m_OnSynchronizePrefab; - private VariableLengthSafety m_VariableLengthSafety; - - private LogLevel m_CurrentLogLevel; - - public enum VariableLengthSafety - { - DisableNetVarSafety, - EnabledNetVarSafety, - }; - - public NetworkObjectSynchronizationTests(VariableLengthSafety variableLengthSafety, HostOrServer hostOrServer) : base(hostOrServer) - { - m_VariableLengthSafety = variableLengthSafety; - } - - protected override void OnCreatePlayerPrefab() - { - var component = m_PlayerPrefab.AddComponent(); - if (m_DistributedAuthority) - { - component.SetWritePermissions(NetworkVariableWritePermission.Owner); - } - base.OnCreatePlayerPrefab(); - } - - protected override void OnServerAndClientsCreated() - { - - // Set the NetworkVariable Safety Check setting - m_ServerNetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety; - - // Ignore the errors generated during this test (they are expected) - m_ServerNetworkManager.LogLevel = LogLevel.Nothing; - - // Disable forcing the same prefabs to avoid failed connections - m_ServerNetworkManager.NetworkConfig.ForceSamePrefabs = false; - - // Create the valid network prefab - m_NetworkPrefab = CreateNetworkObjectPrefab("ValidObject"); - m_NetworkPrefab.AddComponent(); - - // Create the invalid network prefab (that will fail on client side) - m_InValidNetworkPrefab = CreateNetworkObjectPrefab("InvalidObject"); - m_InValidNetworkPrefab.AddComponent(); - - // Create the synchronization network prefab (some pass and some fail) - m_SynchronizationPrefab = CreateNetworkObjectPrefab("SyncObject"); - m_SynchronizationPrefab.AddComponent(); - m_SynchronizationPrefab.AddComponent(); - - m_OnSynchronizePrefab = CreateNetworkObjectPrefab("OnSyncObject"); - m_OnSynchronizePrefab.AddComponent(); - - base.OnServerAndClientsCreated(); - } - - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab; - networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety; - foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) - { - // To simulate a failure, we exclude the m_InValidNetworkPrefab from the connecting - // client's side. - if (networkPrefab.Prefab.name != m_InValidNetworkPrefab.name) - { - networkManager.NetworkConfig.Prefabs.Add(networkPrefab); - } - } - // Disable forcing the same prefabs to avoid failed connections - networkManager.NetworkConfig.ForceSamePrefabs = false; - networkManager.LogLevel = m_CurrentLogLevel; - base.OnNewClientCreated(networkManager); - } - - [UnityTest] - public IEnumerator NetworkObjectDeserializationFailure() - { - m_CurrentLogLevel = LogLevel.Nothing; - var validSpawnedNetworkObjects = new List(); - NetworkBehaviourWithNetworkVariables.ResetSpawnCount(); - - // Spawn NetworkObjects on the server side with half of them being the - // invalid network prefabs to simulate NetworkObject synchronization failure - for (int i = 0; i < k_NumberToSpawn; i++) - { - if (i % 2 == 0) - { - SpawnObject(m_InValidNetworkPrefab, m_ServerNetworkManager); - } - else - { - // Keep track of the prefabs that should successfully spawn on the client side - validSpawnedNetworkObjects.Add(SpawnObject(m_NetworkPrefab, m_ServerNetworkManager)); - } - } - - // Assure the server-side spawned all NetworkObjects - yield return WaitForConditionOrTimeOut(() => NetworkBehaviourWithNetworkVariables.ServerSpawnCount == k_NumberToSpawn); - - // Now spawn and connect a client that will fail to spawn half of the NetworkObjects spawned - yield return CreateAndStartNewClient(); - - if (m_UseHost) - { - var delayCounter = 0; - while (m_ClientNetworkManagers.Length == 0) - { - delayCounter++; - Assert.True(delayCounter < 30, "TimeOut waiting for client to spawn!"); - yield return s_DefaultWaitForTick; - } - delayCounter = 0; - while (!m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_ClientNetworkManagers[0].LocalClientId)) - { - delayCounter++; - if (delayCounter >= 30) - { - VerboseDebug("Trap!"); - } - Assert.True(delayCounter < 30, "TimeOut waiting for client to spawn!"); - yield return s_DefaultWaitForTick; - } - - - var serverSideClientPlayerComponent = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - var serverSideHostPlayerComponent = m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent(); - var clientSidePlayerComponent = m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - var clientSideHostPlayerComponent = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ServerNetworkManager.LocalClientId].GetComponent(); - var modeText = m_DistributedAuthority ? "owner" : "server"; - // Validate that the client side player values match the server side value of the client's player - Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData1.Value == clientSidePlayerComponent.NetworkVariableData1.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Client Player-{clientSidePlayerComponent.OwnerClientId}] Client side value ({clientSidePlayerComponent.NetworkVariableData1.Value})" + - $" does not equal the {modeText} side value ({serverSideClientPlayerComponent.NetworkVariableData1.Value})!"); - Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData2.Value == clientSidePlayerComponent.NetworkVariableData2.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Client Player-{clientSidePlayerComponent.OwnerClientId}] Client side value ({clientSidePlayerComponent.NetworkVariableData2.Value})" + - $" does not equal the {modeText} side value ({serverSideClientPlayerComponent.NetworkVariableData2.Value})!"); - Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData3.Value == clientSidePlayerComponent.NetworkVariableData3.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Client Player-{clientSidePlayerComponent.OwnerClientId}] Client side value ({clientSidePlayerComponent.NetworkVariableData3.Value})" + - $" does not equal the {modeText} side value ({serverSideClientPlayerComponent.NetworkVariableData3.Value})!"); - Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData4.Value == clientSidePlayerComponent.NetworkVariableData4.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Client Player-{clientSidePlayerComponent.OwnerClientId}] Client side value ({clientSidePlayerComponent.NetworkVariableData4.Value})" + - $" does not equal the {modeText} side value ({serverSideClientPlayerComponent.NetworkVariableData4.Value})!"); - - // DANGO-TODO: This scenario is only possible to do if we add a DA-Server to mock the CMB Service or we integrate the CMB Service AND we have updated NetworkVariable permissions - // to only allow the service to write. For now, we will skip this validation for distributed authority - if (!m_DistributedAuthority) - { - // Validate that only the 2nd and 4th NetworkVariable on the client side instance of the host's player is the same and the other two do not match - // (i.e. NetworkVariables owned by the server should not get synchronized on client) - Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData1.Value != clientSideHostPlayerComponent.NetworkVariableData1.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Host Player] Client side value ({clientSideHostPlayerComponent.NetworkVariableData1.Value})" + - $" should not be equal to the server side value ({serverSideHostPlayerComponent.NetworkVariableData1.Value})!"); - Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData2.Value == clientSideHostPlayerComponent.NetworkVariableData2.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Host Player] Client side value ({clientSideHostPlayerComponent.NetworkVariableData2.Value})" + - $" does not equal the server side value ({serverSideHostPlayerComponent.NetworkVariableData2.Value})!"); - Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData3.Value != clientSideHostPlayerComponent.NetworkVariableData3.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Host Player] Client side value ({clientSideHostPlayerComponent.NetworkVariableData3.Value})" + - $" should not be equal to the server side value ({serverSideHostPlayerComponent.NetworkVariableData3.Value})!"); - Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData4.Value == serverSideHostPlayerComponent.NetworkVariableData4.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Host Player] Client side value ({clientSideHostPlayerComponent.NetworkVariableData4.Value})" + - $" does not equal the server side value ({serverSideHostPlayerComponent.NetworkVariableData4.Value})!"); - } - } - else - { - // Spawn and connect another client when running as a server - yield return CreateAndStartNewClient(); - yield return WaitForConditionOrTimeOut(() => m_PlayerNetworkObjects[2].Count > 1); - AssertOnTimeout($"Timed out waiting for second client to have access to the first client's cloned player object!"); - - var clientSide1PlayerComponent = m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - var clientSide2Player1Clone = m_PlayerNetworkObjects[2][clientSide1PlayerComponent.OwnerClientId].GetComponent(); - var clientOneId = clientSide1PlayerComponent.OwnerClientId; - - var clientSide2PlayerComponent = m_ClientNetworkManagers[1].LocalClient.PlayerObject.GetComponent(); - var clientSide1Player2Clone = m_PlayerNetworkObjects[1][clientSide2PlayerComponent.OwnerClientId].GetComponent(); - var clientTwoId = clientSide2PlayerComponent.OwnerClientId; - - // Validate that client one's 2nd and 4th NetworkVariables for the local and clone instances match and the other two do not - Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData1.Value != clientSide2Player1Clone.NetworkVariableData1.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData1.Value})" + - $" should not be equal to Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData1.Value})!"); - - Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData2.Value == clientSide2Player1Clone.NetworkVariableData2.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData2.Value})" + - $" does not equal Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData2.Value})!"); - - Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData3.Value != clientSide2Player1Clone.NetworkVariableData3.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData3.Value})" + - $" should not be equal to Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData3.Value})!"); - - Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData4.Value == clientSide2Player1Clone.NetworkVariableData4.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData4.Value})" + - $" does not equal Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData4.Value})!"); - - // DANGO-TODO: This scenario is only possible to do if we add a DA-Server to mock the CMB Service or we integrate the CMB Service AND we have updated NetworkVariable permissions - // to only allow the service to write. For now, we will skip this validation for distributed authority - if (!m_DistributedAuthority) - { - // Validate that client two's 2nd and 4th NetworkVariables for the local and clone instances match and the other two do not - Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData1.Value != clientSide1Player2Clone.NetworkVariableData1.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData1.Value})" + - $" should not be equal to Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData1.Value})!"); - - Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData2.Value == clientSide1Player2Clone.NetworkVariableData2.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData2.Value})" + - $" does not equal Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData2.Value})!"); - - Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData3.Value != clientSide1Player2Clone.NetworkVariableData3.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData3.Value})" + - $" should not be equal to Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData3.Value})!"); - - Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData4.Value == clientSide1Player2Clone.NetworkVariableData4.Value, - $"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData4.Value})" + - $" does not equal Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData4.Value})!"); - } - } - - // DANGO-TODO: This scenario is only possible to do if we add a DA-Server to mock the CMB Service or we integrate the CMB Service AND we have updated NetworkVariable permissions - // to only allow the service to write. For now, we will skip this validation for distributed authority - if (!m_DistributedAuthority) - { - // Now validate all of the NetworkVariable values match to assure everything synchronized properly - foreach (var spawnedObject in validSpawnedNetworkObjects) - { - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - //Validate that the connected client has spawned all of the instances that shouldn't have failed. - var clientSideNetworkObjects = s_GlobalNetworkObjects[clientNetworkManager.LocalClientId]; - - Assert.IsTrue(NetworkBehaviourWithNetworkVariables.ClientSpawnCount[clientNetworkManager.LocalClientId] == validSpawnedNetworkObjects.Count, $"Client-{clientNetworkManager.LocalClientId} spawned " + - $"({NetworkBehaviourWithNetworkVariables.ClientSpawnCount}) {nameof(NetworkObject)}s but the expected number of {nameof(NetworkObject)}s should have been ({validSpawnedNetworkObjects.Count})!"); - - var spawnedNetworkObject = spawnedObject.GetComponent(); - Assert.IsTrue(clientSideNetworkObjects.ContainsKey(spawnedNetworkObject.NetworkObjectId), $"Failed to find valid spawned {nameof(NetworkObject)} on the client-side with a " + - $"{nameof(NetworkObject.NetworkObjectId)} of {spawnedNetworkObject.NetworkObjectId}"); - - var clientSideObject = clientSideNetworkObjects[spawnedNetworkObject.NetworkObjectId]; - Assert.IsTrue(clientSideObject.NetworkManager == clientNetworkManager, $"Client-side object {clientSideObject}'s {nameof(NetworkManager)} is not valid!"); - - ValidateNetworkBehaviourWithNetworkVariables(spawnedNetworkObject, clientSideObject); - } - } - } - } - - private void ValidateNetworkBehaviourWithNetworkVariables(NetworkObject serverSideNetworkObject, NetworkObject clientSideNetworkObject) - { - var serverSideComponent = serverSideNetworkObject.GetComponent(); - var clientSideComponent = clientSideNetworkObject.GetComponent(); - - string netVarName1 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1); - string netVarName2 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1); - string netVarName3 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1); - string netVarName4 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1); - - Assert.IsTrue(serverSideComponent.NetworkVariableData1.Count == clientSideComponent.NetworkVariableData1.Count, $"[{serverSideComponent.name}:{netVarName1}] Server side {nameof(NetworkList)} " + - $"count ({serverSideComponent.NetworkVariableData1.Count}) does not match the client side {nameof(NetworkList)} count ({clientSideComponent.NetworkVariableData1.Count})!"); - - for (int i = 0; i < serverSideComponent.NetworkVariableData1.Count; i++) - { - Assert.IsTrue(serverSideComponent.NetworkVariableData1[i] == clientSideComponent.NetworkVariableData1[i], $"[{serverSideComponent.name}:{netVarName1}][Index:{i}] Server side instance value " + - $"({serverSideComponent.NetworkVariableData1[i]}) does not match the client side instance value ({clientSideComponent.NetworkVariableData1[i]})!"); - } - - Assert.IsTrue(serverSideComponent.NetworkVariableData2.Value == clientSideComponent.NetworkVariableData2.Value, $"[{serverSideComponent.name}:{netVarName2}] Server side instance value ({serverSideComponent.NetworkVariableData2.Value}) " + - $"does not match the client side instance value ({clientSideComponent.NetworkVariableData2.Value})!"); - Assert.IsTrue(serverSideComponent.NetworkVariableData3.Value == clientSideComponent.NetworkVariableData3.Value, $"[{serverSideComponent.name}:{netVarName3}] Server side instance value ({serverSideComponent.NetworkVariableData3.Value}) " + - $"does not match the client side instance value ({clientSideComponent.NetworkVariableData3.Value})!"); - Assert.IsTrue(serverSideComponent.NetworkVariableData4.Value == clientSideComponent.NetworkVariableData4.Value, $"[{serverSideComponent.name}:{netVarName4}] Server side instance value ({serverSideComponent.NetworkVariableData4.Value}) " + - $"does not match the client side instance value ({clientSideComponent.NetworkVariableData4.Value})!"); - } - - - private bool ClientSpawnedNetworkObjects(List spawnedObjectList) - { - var clientSideNetworkObjects = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId]; - - foreach (var spawnedObject in spawnedObjectList) - { - var serverSideSpawnedNetworkObject = spawnedObject.GetComponent(); - if (!clientSideNetworkObjects.ContainsKey(serverSideSpawnedNetworkObject.NetworkObjectId)) - { - return false; - } - } - return true; - } - - /// - /// This validates that when a NetworkBehaviour fails serialization or deserialization during synchronizations that other NetworkBehaviours - /// will still be initialized properly - /// - [UnityTest] - public IEnumerator NetworkBehaviourSynchronization() - { - m_ServerNetworkManager.LogLevel = LogLevel.Normal; - m_CurrentLogLevel = LogLevel.Normal; - NetworkBehaviourSynchronizeFailureComponent.ResetBehaviour(); - - var spawnedObjectList = new List(); - var numberOfObjectsToSpawn = NetworkBehaviourSynchronizeFailureComponent.NumberOfFailureTypes * 4; - // Spawn 11 more NetworkObjects where there should be 4 of each failure type - for (int i = 0; i < numberOfObjectsToSpawn; i++) - { - var synchronizationObject = SpawnObject(m_SynchronizationPrefab, m_ServerNetworkManager); - var synchronizationBehaviour = synchronizationObject.GetComponent(); - synchronizationBehaviour.AssignNextFailureType(); - spawnedObjectList.Add(synchronizationObject); - } - - // Now spawn and connect a client that will fail to spawn half of the NetworkObjects spawned - yield return CreateAndStartNewClient(); - - // Validate that when a NetworkBehaviour fails to synchronize and is skipped over it does not - // impact the rest of the NetworkBehaviours. - var clientSideNetworkObjects = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId]; - yield return WaitForConditionOrTimeOut(() => ClientSpawnedNetworkObjects(spawnedObjectList)); - AssertOnTimeout($"Timed out waiting for newly joined client to spawn all NetworkObjects!"); - - foreach (var spawnedObject in spawnedObjectList) - { - var serverSideSpawnedNetworkObject = spawnedObject.GetComponent(); - var clientSideObject = clientSideNetworkObjects[serverSideSpawnedNetworkObject.NetworkObjectId]; - var clientSideSpawnedNetworkObject = clientSideObject.GetComponent(); - - ValidateNetworkBehaviourWithNetworkVariables(serverSideSpawnedNetworkObject, clientSideSpawnedNetworkObject); - } - } - - /// - /// A basic validation for the NetworkBehaviour.OnSynchronize method - /// - [UnityTest] - public IEnumerator NetworkBehaviourOnSynchronize() - { - var serverSideInstance = SpawnObject(m_OnSynchronizePrefab, m_ServerNetworkManager).GetComponent(); - - // Now spawn and connect a client that will have custom serialized data applied during the client synchronization process. - yield return CreateAndStartNewClient(); - - var clientSideNetworkObjects = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId]; - var clientSideInstance = clientSideNetworkObjects[serverSideInstance.NetworkObjectId].GetComponent(); - - // Validate the values match - Assert.IsTrue(serverSideInstance.CustomSerializationData.Value1 == clientSideInstance.CustomSerializationData.Value1, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value1}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value1})"); - Assert.IsTrue(serverSideInstance.CustomSerializationData.Value2 == clientSideInstance.CustomSerializationData.Value2, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value2}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value2})"); - Assert.IsTrue(serverSideInstance.CustomSerializationData.Value3 == clientSideInstance.CustomSerializationData.Value3, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value3}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value3})"); - Assert.IsTrue(serverSideInstance.CustomSerializationData.Value4 == clientSideInstance.CustomSerializationData.Value4, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value4}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value4})"); - } - } - - /// - /// A test NetworkBeahviour that provides a varying NetworkList size as well as - /// additional NetworkVariables to assure if a NetworkObject fails to be created - /// the synchronization process will continue (i.e. it will skip over that block - /// of the reader buffer). - /// - internal class NetworkBehaviourWithNetworkVariables : NetworkBehaviour - { - public static int ServerSpawnCount { get; internal set; } - public static readonly Dictionary ClientSpawnCount = new Dictionary(); - - public static void ResetSpawnCount() - { - ServerSpawnCount = 0; - ClientSpawnCount.Clear(); - } - - private const uint k_MinDataBlocks = 1; - private const uint k_MaxDataBlocks = 64; - - // Add various types of NetworkVariables - public NetworkList NetworkVariableData1; - public NetworkVariable NetworkVariableData2; - public NetworkVariable NetworkVariableData3; - public NetworkVariable NetworkVariableData4; - - private void Awake() - { - var dataBlocksAssigned = new List(); - var numberDataBlocks = Random.Range(k_MinDataBlocks, k_MaxDataBlocks); - for (var i = 0; i < numberDataBlocks; i++) - { - dataBlocksAssigned.Add((ulong)Random.Range(0.0f, float.MaxValue)); - } - - NetworkVariableData1 = new NetworkList(dataBlocksAssigned); - NetworkVariableData2 = new NetworkVariable(Random.Range(1, 1000)); - NetworkVariableData3 = new NetworkVariable(Random.Range(1, 1000)); - NetworkVariableData4 = new NetworkVariable((byte)Random.Range(1, 255)); - - } - - public override void OnNetworkSpawn() - { - if (IsServer) - { - ServerSpawnCount++; - } - else - { - if (!ClientSpawnCount.ContainsKey(NetworkManager.LocalClientId)) - { - ClientSpawnCount.Add(NetworkManager.LocalClientId, 0); - } - ClientSpawnCount[NetworkManager.LocalClientId]++; - } - - base.OnNetworkSpawn(); - } - } - - /// - /// A test NetworkBeahviour that has varying permissions in order to validate that - /// when variable length safety checks are off NetworkVariables still are updated - /// properly. - /// - internal class NetworkBehaviourWithOwnerNetworkVariables : NetworkBehaviour - { - private NetworkVariableWritePermission m_NetworkVariableWritePermission = NetworkVariableWritePermission.Server; - /// - /// For distributed authority, there is no such thing as a server and only owners - /// DANGO-TODO: When NetworkVariable permissions are updated, this test might need to be updated - /// - /// - public void SetWritePermissions(NetworkVariableWritePermission networkVariableWritePermission) - { - m_NetworkVariableWritePermission = networkVariableWritePermission; - // Should synchronize with everyone - NetworkVariableData1 = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, networkVariableWritePermission); - // Should synchronize with everyone - NetworkVariableData2 = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, networkVariableWritePermission); - // Should synchronize with everyone - NetworkVariableData3 = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, networkVariableWritePermission); - // Should synchronize with everyone - NetworkVariableData4 = new NetworkVariable(default, NetworkVariableReadPermission.Everyone, networkVariableWritePermission); - } - - // Should not synchronize on non-owners - public NetworkVariable NetworkVariableData1 = new NetworkVariable(default, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server); - // Should synchronize with everyone - public NetworkVariable NetworkVariableData2 = new NetworkVariable(); - // Should not synchronize on non-owners - public NetworkVariable NetworkVariableData3 = new NetworkVariable(default, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server); - // Should synchronize with everyone - public NetworkVariable NetworkVariableData4 = new NetworkVariable(); - - public override void OnNetworkSpawn() - { - // Adjustment for distributed authority mode - if ((m_NetworkVariableWritePermission == NetworkVariableWritePermission.Server && IsServer && !NetworkManager.DistributedAuthorityMode) || - (m_NetworkVariableWritePermission == NetworkVariableWritePermission.Owner && IsOwner && NetworkManager.DistributedAuthorityMode)) - { - NetworkVariableData1.Value = Random.Range(1, 1000); - NetworkVariableData2.Value = Random.Range(1, 1000); - NetworkVariableData3.Value = (byte)Random.Range(1, 255); - NetworkVariableData4.Value = (ushort)Random.Range(1, ushort.MaxValue); - } - } - } - - /// - /// A test NetworkBeahviour that simulates various types of synchronization failures - /// and provides a synchronization success version to validate that synchronization - /// will continue if user synchronization code fails. - /// - internal class NetworkBehaviourSynchronizeFailureComponent : NetworkBehaviour - { - public static int NumberOfFailureTypes { get; internal set; } - public static int ServerSpawnCount { get; internal set; } - public static int ClientSpawnCount { get; internal set; } - - private static FailureTypes s_FailureType = FailureTypes.None; - - public enum FailureTypes - { - None, - DuringWriting, - DuringReading, - DontReadAnything, - ThrowWriteSideException, - ThrowReadSideException - } - - public static void ResetBehaviour() - { - ServerSpawnCount = 0; - ClientSpawnCount = 0; - s_FailureType = FailureTypes.None; - NumberOfFailureTypes = System.Enum.GetValues(typeof(FailureTypes)).Length; - } - - private MyCustomData m_MyCustomData; - - private struct MyCustomData : INetworkSerializable - { - public FailureTypes FailureType; - private ushort m_DataSize; - private byte[] m_DataBlock; - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - if (serializer.IsWriter) - { - var writer = serializer.GetFastBufferWriter(); - switch (FailureType) - { - case FailureTypes.None: - // We want to write something for these two cases - case FailureTypes.DuringReading: - case FailureTypes.DontReadAnything: - { - writer.WriteValueSafe(m_DataSize); - for (int i = 0; i < m_DataSize; i++) - { - writer.WriteValueSafe(m_DataBlock[i]); - } - break; - } - case FailureTypes.DuringWriting: - { - writer.WriteValueSafe(m_DataSize); - // Try to write past the allocated size to generate an exception - // while also filling the buffer to verify that the buffer will be - // reset back to the original position. - for (int i = 0; i <= m_DataSize; i++) - { - writer.WriteValueSafe(m_DataBlock[i]); - } - break; - } - case FailureTypes.ThrowWriteSideException: - { - throw new System.Exception("Write side exception!"); - } - } - } - else - { - var reader = serializer.GetFastBufferReader(); - switch (FailureType) - { - case FailureTypes.None: - { - reader.ReadValueSafe(out m_DataSize); - m_DataBlock = new byte[m_DataSize]; - for (int i = 0; i < m_DataSize; i++) - { - reader.ReadValueSafe(out m_DataBlock[i]); - } - break; - } - case FailureTypes.DuringReading: - { - reader.ReadValueSafe(out m_DataSize); - // Allocate more space than needed - m_DataBlock = new byte[(int)(m_DataSize * 1.5f)]; - // Now read past the size of this message to verify - // that the reader will get rest back to the appropriate - // position and an error will be generated for this - for (int i = 0; i < m_DataBlock.Length; i++) - { - reader.ReadValueSafe(out m_DataBlock[i]); - } - break; - } - case FailureTypes.DontReadAnything: - { - // Don't read anything - break; - } - case FailureTypes.ThrowReadSideException: - { - throw new System.Exception("Read side exception!"); - } - - } - } - } - - public void GenerateData(ushort size) - { - m_DataSize = size; - m_DataBlock = new byte[size]; - for (int i = 0; i < m_DataSize; i++) - { - m_DataBlock[i] = (byte)Random.Range(0, 512); - } - } - } - - // This NetworkVariable is synchronized before OnSynchronize is invoked - // which enables us to perform the tests. - // Users could follow the same pattern for game assets and synchronize - // clients based on NetworkVariable settings. (i.e. a specific NPC type or the like) - private NetworkVariable m_FailureType; - - public void AssignNextFailureType() - { - var currentPosition = (int)s_FailureType; - currentPosition = (++currentPosition) % NumberOfFailureTypes; - s_FailureType = (FailureTypes)currentPosition; - m_FailureType.Value = s_FailureType; - } - - - private void Awake() - { - m_FailureType = new NetworkVariable(); - m_MyCustomData = new MyCustomData(); - } - - public override void OnNetworkSpawn() - { - if (IsServer) - { - ServerSpawnCount++; - m_MyCustomData.GenerateData((ushort)Random.Range(1, 512)); - } - else - { - ClientSpawnCount++; - } - - base.OnNetworkSpawn(); - } - - protected override void OnSynchronize(ref BufferSerializer serializer) - { - // Assign the failure type first - m_MyCustomData.FailureType = m_FailureType.Value; - // Now handle the serialization for this failure type - m_MyCustomData.NetworkSerialize(serializer); - } - } - - internal class NetworkBehaviourOnSynchronizeComponent : NetworkBehaviour - { - public SomeCustomSerializationData CustomSerializationData = new SomeCustomSerializationData(); - - internal struct SomeCustomSerializationData : INetworkSerializable - { - public uint Value1; - public bool Value2; - public long Value3; - public float Value4; - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Value1); - serializer.SerializeValue(ref Value2); - serializer.SerializeValue(ref Value3); - serializer.SerializeValue(ref Value4); - } - } - - public override void OnNetworkSpawn() - { - if (IsServer) - { - CustomSerializationData.Value1 = (uint)Random.Range(0, 10000); - CustomSerializationData.Value2 = true; - CustomSerializationData.Value3 = Random.Range(0, 10000); - CustomSerializationData.Value4 = Random.Range(-1000.0f, 1000.0f); - } - base.OnNetworkSpawn(); - } - - protected override void OnSynchronize(ref BufferSerializer serializer) - { - serializer.SerializeNetworkSerializable(ref CustomSerializationData); - base.OnSynchronize(ref serializer); - } - } -} diff --git a/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs.meta b/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs.meta deleted file mode 100644 index 39e88d4..0000000 --- a/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c8e27bb7c831a8f49884a8af5e59f2f9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkPrefabHandlerTests.cs b/Tests/Runtime/NetworkPrefabHandlerTests.cs deleted file mode 100644 index 2dc5f60..0000000 --- a/Tests/Runtime/NetworkPrefabHandlerTests.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// The NetworkPrefabHandler unit tests validates: - /// Registering with GameObject, NetworkObject, or GlobalObjectIdHash - /// Newly assigned rotation or position values for newly spawned NetworkObject instances are valid - /// Destroying a newly spawned NetworkObject instance works - /// Removing a INetworkPrefabInstanceHandler is removed and can be verified (very last check) - /// - internal class NetworkPrefabHandlerTests - { - - private const string k_TestPrefabObjectName = "NetworkPrefabTestObject"; - private uint m_ObjectId = 1; - private GameObject MakeValidNetworkPrefab() - { - Guid baseObjectID = NetworkManagerHelper.AddGameNetworkObject(k_TestPrefabObjectName + m_ObjectId.ToString()); - NetworkObject validPrefab = NetworkManagerHelper.InstantiatedNetworkObjects[baseObjectID]; - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(validPrefab); - m_ObjectId++; - return validPrefab.gameObject; - } - - /// - /// Tests the NetwokConfig NetworkPrefabsList initialization during NetworkManager's Init method to make sure that - /// it will still initialize but remove the invalid prefabs - /// - [Test] - public void NetworkConfigInvalidNetworkPrefabTest() - { - - // Add null entry - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(null); - - // Add a NetworkPrefab with no prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab()); - - // Add a NetworkPrefab override with an invalid hash - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Hash, SourceHashToOverride = 0 }); - - // Add a NetworkPrefab override with a valid hash but an invalid target prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Hash, SourceHashToOverride = 654321, OverridingTargetPrefab = null }); - - // Add a NetworkPrefab override with a valid hash to override but an invalid target prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Prefab, SourceHashToOverride = 654321, OverridingTargetPrefab = null }); - - // Add a NetworkPrefab override with an invalid source prefab to override - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Prefab, SourcePrefabToOverride = null }); - - // Add a NetworkPrefab override with a valid source prefab to override but an invalid target prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Prefab, SourcePrefabToOverride = MakeValidNetworkPrefab(), OverridingTargetPrefab = null }); - - // Add a valid prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Prefab = MakeValidNetworkPrefab() }); - - // Add a NetworkPrefab override with a valid hash and valid target prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Hash, SourceHashToOverride = 11111111, OverridingTargetPrefab = MakeValidNetworkPrefab() }); - - // Add a NetworkPrefab override with a valid prefab and valid target prefab - NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.Prefab, SourcePrefabToOverride = MakeValidNetworkPrefab(), OverridingTargetPrefab = MakeValidNetworkPrefab() }); - - var exceptionOccurred = false; - try - { - NetworkManagerHelper.NetworkManagerObject.StartHost(); - } - catch - { - exceptionOccurred = true; - } - - Assert.False(exceptionOccurred); - - // In the end we should only have 3 valid registered network prefabs - Assert.True(NetworkManagerHelper.NetworkManagerObject.NetworkConfig.Prefabs.NetworkPrefabOverrideLinks.Count == 3); - } - - private const string k_PrefabObjectName = "NetworkPrefabHandlerTestObject"; - - [Test] - public void NetworkPrefabHandlerClass() - { - Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _)); - var testPrefabObjectName = k_PrefabObjectName; - - Guid baseObjectID = NetworkManagerHelper.AddGameNetworkObject(testPrefabObjectName); - NetworkObject baseObject = NetworkManagerHelper.InstantiatedNetworkObjects[baseObjectID]; - - var networkPrefabHandler = new NetworkPrefabHandler(); - var networkPrefaInstanceHandler = new NetworkPrefaInstanceHandler(baseObject); - - var prefabPosition = new Vector3(1.0f, 5.0f, 3.0f); - var prefabRotation = new Quaternion(1.0f, 0.5f, 0.4f, 0.1f); - - //Register via GameObject - var gameObjectRegistered = networkPrefabHandler.AddHandler(baseObject.gameObject, networkPrefaInstanceHandler); - - //Test result of registering via GameObject reference - Assert.True(gameObjectRegistered); - - var spawnedObject = networkPrefabHandler.HandleNetworkPrefabSpawn(baseObject.GlobalObjectIdHash, 0, prefabPosition, prefabRotation); - - //Test that something was instantiated - Assert.NotNull(spawnedObject); - - //Test that this is indeed an instance of our original object - Assert.True(spawnedObject.name.Contains(testPrefabObjectName)); - - //Test for position and rotation - Assert.True(prefabPosition == spawnedObject.transform.position); - Assert.True(prefabRotation == spawnedObject.transform.rotation); - - networkPrefabHandler.HandleNetworkPrefabDestroy(spawnedObject); //Destroy our prefab instance - networkPrefabHandler.RemoveHandler(baseObject); //Remove our handler - - //Register via NetworkObject - gameObjectRegistered = networkPrefabHandler.AddHandler(baseObject, networkPrefaInstanceHandler); - - //Test result of registering via NetworkObject reference - Assert.True(gameObjectRegistered); - - //Change it up - prefabPosition = new Vector3(2.0f, 1.0f, 5.0f); - prefabRotation = new Quaternion(4.0f, 1.5f, 5.4f, 5.1f); - - spawnedObject = networkPrefabHandler.HandleNetworkPrefabSpawn(baseObject.GlobalObjectIdHash, 0, prefabPosition, prefabRotation); - - //Test that something was instantiated - Assert.NotNull(spawnedObject); - - //Test that this is indeed an instance of our original object - Assert.True(spawnedObject.name.Contains(testPrefabObjectName)); - - //Test for position and rotation - Assert.True(prefabPosition == spawnedObject.transform.position); - Assert.True(prefabRotation == spawnedObject.transform.rotation); - - networkPrefabHandler.HandleNetworkPrefabDestroy(spawnedObject); //Destroy our prefab instance - networkPrefabHandler.RemoveHandler(baseObject); //Remove our handler - - //Register via GlobalObjectIdHash - gameObjectRegistered = networkPrefabHandler.AddHandler(baseObject.GlobalObjectIdHash, networkPrefaInstanceHandler); - - //Test result of registering via GlobalObjectIdHash reference - Assert.True(gameObjectRegistered); - - //Change it up - prefabPosition = new Vector3(6.0f, 4.0f, 1.0f); - prefabRotation = new Quaternion(3f, 2f, 4f, 1f); - - spawnedObject = networkPrefabHandler.HandleNetworkPrefabSpawn(baseObject.GlobalObjectIdHash, 0, prefabPosition, prefabRotation); - - //Test that something was instantiated - Assert.NotNull(spawnedObject); - - //Test that this is indeed an instance of our original object - Assert.True(spawnedObject.name.Contains(testPrefabObjectName)); - - //Test for position and rotation - Assert.True(prefabPosition == spawnedObject.transform.position); - Assert.True(prefabRotation == spawnedObject.transform.rotation); - - networkPrefabHandler.HandleNetworkPrefabDestroy(spawnedObject); //Destroy our prefab instance - networkPrefabHandler.RemoveHandler(baseObject); //Remove our handler - - Assert.False(networkPrefaInstanceHandler.StillHasInstances()); - } - - [SetUp] - public void Setup() - { - //Create, instantiate, and host - NetworkManagerHelper.StartNetworkManager(out _, NetworkManagerHelper.NetworkManagerOperatingMode.None); - } - - [TearDown] - public void TearDown() - { - //Stop, shutdown, and destroy - NetworkManagerHelper.ShutdownNetworkManager(); - -#if UNITY_2023_1_OR_NEWER - var networkObjects = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.InstanceID).ToList(); -#else - var networkObjects = UnityEngine.Object.FindObjectsOfType().ToList(); -#endif - - var networkObjectsList = networkObjects.Where(c => c.name.Contains(k_PrefabObjectName)); - foreach (var networkObject in networkObjectsList) - { - UnityEngine.Object.DestroyImmediate(networkObject); - } - } - } - - /// - /// The Prefab instance handler to use for this test - /// - internal class NetworkPrefaInstanceHandler : INetworkPrefabInstanceHandler - { - private NetworkObject m_NetworkObject; - - private List m_Instances; - - public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) - { - var networkObjectInstance = UnityEngine.Object.Instantiate(m_NetworkObject.gameObject).GetComponent(); - networkObjectInstance.transform.position = position; - networkObjectInstance.transform.rotation = rotation; - m_Instances.Add(networkObjectInstance); - return networkObjectInstance; - } - - public void Destroy(NetworkObject networkObject) - { - var instancesContainsNetworkObject = m_Instances.Contains(networkObject); - Assert.True(instancesContainsNetworkObject); - m_Instances.Remove(networkObject); - UnityEngine.Object.Destroy(networkObject.gameObject); - } - - public bool StillHasInstances() - { - return (m_Instances.Count > 0); - } - - public NetworkPrefaInstanceHandler(NetworkObject networkObject) - { - m_NetworkObject = networkObject; - m_Instances = new List(); - } - } -} diff --git a/Tests/Runtime/NetworkPrefabHandlerTests.cs.meta b/Tests/Runtime/NetworkPrefabHandlerTests.cs.meta deleted file mode 100644 index 334e3eb..0000000 --- a/Tests/Runtime/NetworkPrefabHandlerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 590750036c5d65c43bbc696071aa3541 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkShowHideTests.cs b/Tests/Runtime/NetworkShowHideTests.cs deleted file mode 100644 index ea01073..0000000 --- a/Tests/Runtime/NetworkShowHideTests.cs +++ /dev/null @@ -1,751 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class ShowHideObject : NetworkBehaviour - { - public static List ClientTargetedNetworkObjects = new List(); - public static ulong ClientIdToTarget; - public static bool Silent; - public static int ValueAfterOwnershipChange = 0; - public static Dictionary ObjectsPerClientId = new Dictionary(); - public static List ClientIdsRpcCalledOn; - public static NetworkObject GetNetworkObjectById(ulong networkObjectId) - { - foreach (var entry in ClientTargetedNetworkObjects) - { - if (entry.NetworkObjectId == networkObjectId) - { - return entry.NetworkObject; - } - } - return null; - } - - public override void OnNetworkSpawn() - { - if (NetworkManager.LocalClientId == ClientIdToTarget) - { - ClientTargetedNetworkObjects.Add(this); - } - - if (IsServer) - { - MyListSetOnSpawn.Add(45); - } - else - { - Debug.Assert(MyListSetOnSpawn.Count == 1); - Debug.Assert(MyListSetOnSpawn[0] == 45); - } - - if (ObjectsPerClientId.ContainsKey(NetworkManager.LocalClientId)) - { - ObjectsPerClientId[NetworkManager.LocalClientId] = this; - } - else - { - ObjectsPerClientId.Add(NetworkManager.LocalClientId, this); - } - - base.OnNetworkSpawn(); - } - - public override void OnNetworkDespawn() - { - if (ClientTargetedNetworkObjects.Contains(this)) - { - ClientTargetedNetworkObjects.Remove(this); - } - base.OnNetworkDespawn(); - } - - public NetworkVariable MyNetworkVariable; - public NetworkList MyListSetOnSpawn; - public NetworkVariable MyOwnerReadNetworkVariable; - public NetworkList MyList; - public static NetworkManager NetworkManagerOfInterest; - - internal static int GainOwnershipCount = 0; - - private void Awake() - { - // Debug.Log($"Awake {NetworkManager.LocalClientId}"); - MyNetworkVariable = new NetworkVariable(); - MyNetworkVariable.OnValueChanged += Changed; - - MyListSetOnSpawn = new NetworkList(); - MyList = new NetworkList(); - - MyOwnerReadNetworkVariable = new NetworkVariable(readPerm: NetworkVariableReadPermission.Owner); - MyOwnerReadNetworkVariable.OnValueChanged += OwnerReadChanged; - } - - public override void OnGainedOwnership() - { - GainOwnershipCount++; - base.OnGainedOwnership(); - } - - public void OwnerReadChanged(int before, int after) - { - if (NetworkManager == NetworkManagerOfInterest) - { - ValueAfterOwnershipChange = after; - } - } - - public void Changed(int before, int after) - { - if (!Silent) - { - Debug.Log($"Value changed from {before} to {after}"); - } - } - - [ClientRpc] - public void SomeRandomClientRPC() - { - if (!Silent) - { - Debug.Log($"RPC called {NetworkManager.LocalClientId}"); - } - ClientIdsRpcCalledOn?.Add(NetworkManager.LocalClientId); - } - - public void TriggerRpc() - { - SomeRandomClientRPC(); - } - } - - [TestFixture(NetworkTopologyTypes.ClientServer)] - [TestFixture(NetworkTopologyTypes.DistributedAuthority)] - internal class NetworkShowHideTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 4; - - private ulong m_ClientId0; - private GameObject m_PrefabToSpawn; - private GameObject m_PrefabSpawnWithoutObservers; - - private NetworkObject m_NetSpawnedObject1; - private NetworkObject m_NetSpawnedObject2; - private NetworkObject m_NetSpawnedObject3; - private NetworkObject m_Object1OnClient0; - private NetworkObject m_Object2OnClient0; - private NetworkObject m_Object3OnClient0; - - public NetworkShowHideTests(NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) { } - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("ShowHideObject"); - m_PrefabToSpawn.AddComponent(); - - m_PrefabSpawnWithoutObservers = CreateNetworkObjectPrefab("ObserversObject"); - m_PrefabSpawnWithoutObservers.GetComponent().SpawnWithObservers = false; - } - - // Check that the first client see them, or not, as expected - private IEnumerator CheckVisible(bool isVisible) - { - int count = 0; - do - { - yield return WaitForTicks(m_ServerNetworkManager, 5); - count++; - - if (count > 20) - { - // timeout waiting for object to reach the expect visibility - Assert.Fail("timeout waiting for object to reach the expect visibility"); - break; - } - } while (m_NetSpawnedObject1.IsNetworkVisibleTo(m_ClientId0) != isVisible || - m_NetSpawnedObject2.IsNetworkVisibleTo(m_ClientId0) != isVisible || - m_NetSpawnedObject3.IsNetworkVisibleTo(m_ClientId0) != isVisible || - m_Object1OnClient0.IsSpawned != isVisible || - m_Object2OnClient0.IsSpawned != isVisible || - m_Object3OnClient0.IsSpawned != isVisible - ); - - Debug.Assert(m_NetSpawnedObject1.IsNetworkVisibleTo(m_ClientId0) == isVisible); - Debug.Assert(m_NetSpawnedObject2.IsNetworkVisibleTo(m_ClientId0) == isVisible); - Debug.Assert(m_NetSpawnedObject3.IsNetworkVisibleTo(m_ClientId0) == isVisible); - - Debug.Assert(m_Object1OnClient0.IsSpawned == isVisible); - Debug.Assert(m_Object2OnClient0.IsSpawned == isVisible); - Debug.Assert(m_Object3OnClient0.IsSpawned == isVisible); - - var clientNetworkManager = m_ClientNetworkManagers.Where((c) => c.LocalClientId == m_ClientId0).First(); - if (isVisible) - { - Assert.True(ShowHideObject.ClientTargetedNetworkObjects.Count == 3, $"Client-{clientNetworkManager.LocalClientId} should have 3 instances visible but only has {ShowHideObject.ClientTargetedNetworkObjects.Count}!"); - } - else - { - Assert.True(ShowHideObject.ClientTargetedNetworkObjects.Count == 0, $"Client-{clientNetworkManager.LocalClientId} should have no visible instances but still has {ShowHideObject.ClientTargetedNetworkObjects.Count}!"); - } - } - - // Set the 3 objects visibility - private void Show(bool individually, bool visibility) - { - if (individually) - { - if (!visibility) - { - m_NetSpawnedObject1.NetworkHide(m_ClientId0); - m_NetSpawnedObject2.NetworkHide(m_ClientId0); - m_NetSpawnedObject3.NetworkHide(m_ClientId0); - } - else - { - m_NetSpawnedObject1.NetworkShow(m_ClientId0); - m_NetSpawnedObject2.NetworkShow(m_ClientId0); - m_NetSpawnedObject3.NetworkShow(m_ClientId0); - } - } - else - { - var list = new List - { - m_NetSpawnedObject1, - m_NetSpawnedObject2, - m_NetSpawnedObject3 - }; - - if (!visibility) - { - NetworkObject.NetworkHide(list, m_ClientId0); - } - else - { - NetworkObject.NetworkShow(list, m_ClientId0); - } - } - } - - private bool RefreshNetworkObjects() - { - m_Object1OnClient0 = ShowHideObject.GetNetworkObjectById(m_NetSpawnedObject1.NetworkObjectId); - m_Object2OnClient0 = ShowHideObject.GetNetworkObjectById(m_NetSpawnedObject2.NetworkObjectId); - m_Object3OnClient0 = ShowHideObject.GetNetworkObjectById(m_NetSpawnedObject3.NetworkObjectId); - if (m_Object1OnClient0 == null || m_Object2OnClient0 == null || m_Object3OnClient0 == null) - { - return false; - } - Assert.True(m_Object1OnClient0.NetworkManagerOwner == m_ClientNetworkManagers[0]); - Assert.True(m_Object2OnClient0.NetworkManagerOwner == m_ClientNetworkManagers[0]); - Assert.True(m_Object3OnClient0.NetworkManagerOwner == m_ClientNetworkManagers[0]); - return true; - } - - - [UnityTest] - public IEnumerator NetworkShowHideTest() - { - m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientId0; - - - // create 3 objects - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject2 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject3 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - m_NetSpawnedObject2 = spawnedObject2.GetComponent(); - m_NetSpawnedObject3 = spawnedObject3.GetComponent(); - - for (int mode = 0; mode < 2; mode++) - { - // get the NetworkObject on a client instance - yield return WaitForConditionOrTimeOut(RefreshNetworkObjects); - AssertOnTimeout($"Could not refresh all NetworkObjects!"); - - // check object start visible - yield return CheckVisible(true); - - // hide them on one client - Show(mode == 0, false); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - m_NetSpawnedObject1.GetComponent().MyNetworkVariable.Value = 3; - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // verify they got hidden - yield return CheckVisible(false); - - // show them to that client - Show(mode == 0, true); - yield return WaitForConditionOrTimeOut(RefreshNetworkObjects); - AssertOnTimeout($"Could not refresh all NetworkObjects!"); - - // verify they become visible - yield return CheckVisible(true); - } - } - - [UnityTest] - public IEnumerator ConcurrentShowAndHideOnDifferentObjects() - { - m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientId0; - - - // create 3 objects - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject2 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject3 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - m_NetSpawnedObject2 = spawnedObject2.GetComponent(); - m_NetSpawnedObject3 = spawnedObject3.GetComponent(); - - // get the NetworkObject on a client instance - yield return WaitForConditionOrTimeOut(RefreshNetworkObjects); - AssertOnTimeout($"Could not refresh all NetworkObjects!"); - - m_NetSpawnedObject1.NetworkHide(m_ClientId0); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - m_NetSpawnedObject1.NetworkShow(m_ClientId0); - m_NetSpawnedObject2.NetworkHide(m_ClientId0); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - } - - [UnityTest] - public IEnumerator NetworkShowHideQuickTest() - { - m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientId0; - - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject2 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject3 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - m_NetSpawnedObject2 = spawnedObject2.GetComponent(); - m_NetSpawnedObject3 = spawnedObject3.GetComponent(); - - for (int mode = 0; mode < 2; mode++) - { - // get the NetworkObject on a client instance - yield return WaitForConditionOrTimeOut(RefreshNetworkObjects); - AssertOnTimeout($"Could not refresh all NetworkObjects!"); - - // check object start visible - yield return CheckVisible(true); - - // hide and show them on one client, during the same frame - Show(mode == 0, false); - Show(mode == 0, true); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - yield return WaitForConditionOrTimeOut(RefreshNetworkObjects); - AssertOnTimeout($"Could not refresh all NetworkObjects!"); - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // verify they become visible - yield return CheckVisible(true); - } - } - - [UnityTest] - public IEnumerator NetworkHideDespawnTest() - { - m_ClientId0 = m_ClientNetworkManagers[0].LocalClientId; - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientId0; - ShowHideObject.Silent = true; - - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject2 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - var spawnedObject3 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - m_NetSpawnedObject2 = spawnedObject2.GetComponent(); - m_NetSpawnedObject3 = spawnedObject3.GetComponent(); - - m_NetSpawnedObject1.GetComponent().MyNetworkVariable.Value++; - m_NetSpawnedObject1.NetworkHide(m_ClientId0); - m_NetSpawnedObject1.Despawn(); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - LogAssert.NoUnexpectedReceived(); - } - - - private List m_ClientsWithVisibility = new List(); - private NetworkObject m_ObserverTestObject; - - private bool CheckListedClientsVisibility() - { - if (m_ClientsWithVisibility.Contains(m_ServerNetworkManager.LocalClientId)) - { - if (!m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(m_ObserverTestObject.NetworkObjectId)) - { - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - if (m_ClientsWithVisibility.Contains(client.LocalClientId)) - { - if (!client.SpawnManager.SpawnedObjects.ContainsKey(m_ObserverTestObject.NetworkObjectId)) - { - return false; - } - } - } - return true; - } - - [UnityTest] - public IEnumerator SpawnWithoutObserversTest() - { - var spawnedObject = SpawnObject(m_PrefabSpawnWithoutObservers, m_ServerNetworkManager); - - m_ObserverTestObject = spawnedObject.GetComponent(); - - yield return WaitForTicks(m_ServerNetworkManager, 3); - - // When in client-server, the server can spawn a NetworkObject without any observers (even when running as a host the host-client should not have visibility) - // When in distributed authority mode, the owner client has to be an observer of the object - if (!m_DistributedAuthority) - { - // No observers should be assigned at this point - Assert.True(m_ObserverTestObject.Observers.Count == m_ClientsWithVisibility.Count, $"Expected the observer count to be {m_ClientsWithVisibility.Count} but it was {m_ObserverTestObject.Observers.Count}!"); - m_ObserverTestObject.NetworkShow(m_ServerNetworkManager.LocalClientId); - } - m_ClientsWithVisibility.Add(m_ServerNetworkManager.LocalClientId); - - Assert.True(m_ObserverTestObject.Observers.Count == m_ClientsWithVisibility.Count, $"Expected the observer count to be {m_ClientsWithVisibility.Count} but it was {m_ObserverTestObject.Observers.Count}!"); - - yield return WaitForConditionOrTimeOut(CheckListedClientsVisibility); - AssertOnTimeout($"[Authority-Only] Timed out waiting for only the authority to be an observer!"); - - foreach (var client in m_ClientNetworkManagers) - { - m_ObserverTestObject.NetworkShow(client.LocalClientId); - m_ClientsWithVisibility.Add(client.LocalClientId); - Assert.True(m_ObserverTestObject.Observers.Contains(client.LocalClientId), $"[NetworkShow] Client-{client.LocalClientId} is still not an observer!"); - Assert.True(m_ObserverTestObject.Observers.Count == m_ClientsWithVisibility.Count, $"Expected the observer count to be {m_ClientsWithVisibility.Count} but it was {m_ObserverTestObject.Observers.Count}!"); - - yield return WaitForConditionOrTimeOut(CheckListedClientsVisibility); - AssertOnTimeout($"[Client-{client.LocalClientId}] Timed out waiting for the client to be an observer and spawn the {nameof(NetworkObject)}!"); - Assert.False(client.SpawnManager.SpawnedObjects[m_ObserverTestObject.NetworkObjectId].SpawnWithObservers, $"Client-{client.LocalClientId} instance of {m_ObserverTestObject.name} has a {nameof(NetworkObject.SpawnWithObservers)} value of true!"); - } - } - - private bool ClientsSpawnedObject1() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!client.SpawnManager.SpawnedObjects.ContainsKey(m_NetSpawnedObject1.NetworkObjectId)) - { - return false; - } - } - return true; - } - - private StringBuilder m_ErrorLog = new StringBuilder(); - private ulong m_ClientWithoutVisibility; - private bool Object1IsNotVisibileToClient() - { - m_ErrorLog.Clear(); - foreach (var client in m_ClientNetworkManagers) - { - if (client.LocalClientId == m_ClientWithoutVisibility) - { - if (client.SpawnManager.SpawnedObjects.ContainsKey(m_NetSpawnedObject1.NetworkObjectId)) - { - m_ErrorLog.AppendLine($"{m_NetSpawnedObject1.name} is still visible to Client-{m_ClientWithoutVisibility}!"); - } - } - else - if (client.SpawnManager.SpawnedObjects[m_NetSpawnedObject1.NetworkObjectId].IsNetworkVisibleTo(m_ClientWithoutVisibility)) - { - m_ErrorLog.AppendLine($"Local instance of {m_NetSpawnedObject1.name} on Client-{client.LocalClientId} thinks Client-{m_ClientWithoutVisibility} still has visibility!"); - } - } - return m_ErrorLog.Length == 0; - } - - [UnityTest] - public IEnumerator NetworkHideChangeOwnership() - { - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientNetworkManagers[1].LocalClientId; - ShowHideObject.Silent = true; - - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - - yield return WaitForConditionOrTimeOut(ClientsSpawnedObject1); - AssertOnTimeout($"Not all clients spawned object!"); - - m_NetSpawnedObject1.GetComponent().MyNetworkVariable.Value++; - // Hide an object to a client - m_NetSpawnedObject1.NetworkHide(m_ClientNetworkManagers[1].LocalClientId); - m_ClientWithoutVisibility = m_ClientNetworkManagers[1].LocalClientId; - - yield return WaitForConditionOrTimeOut(Object1IsNotVisibileToClient); - AssertOnTimeout($"NetworkObject is still visible to Client-{m_ClientWithoutVisibility} or other clients think it is still visible to Client-{m_ClientWithoutVisibility}:\n {m_ErrorLog}"); - - yield return WaitForConditionOrTimeOut(() => ShowHideObject.ClientTargetedNetworkObjects.Count == 0); - - foreach (var client in m_ClientNetworkManagers) - { - if (m_ClientNetworkManagers[1].LocalClientId == client.LocalClientId) - { - continue; - } - var clientInstance = client.SpawnManager.SpawnedObjects[m_NetSpawnedObject1.NetworkObjectId]; - Assert.IsFalse(clientInstance.IsNetworkVisibleTo(m_ClientNetworkManagers[1].LocalClientId), $"Object instance on Client-{client.LocalClientId} is still visible to Client-{m_ClientNetworkManagers[1].LocalClientId}!"); - } - - // Change ownership while the object is hidden to some - m_NetSpawnedObject1.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - // The two-second wait is actually needed as there's a potential warning of unhandled message after 1 second - yield return new WaitForSeconds(1.25f); - - LogAssert.NoUnexpectedReceived(); - // Show the object again to check nothing unexpected happens - if (m_DistributedAuthority) - { - Assert.True(m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects.ContainsKey(m_NetSpawnedObject1.NetworkObjectId), $"Client-{m_ClientNetworkManagers[0].LocalClientId} has no spawned object with an ID of: {m_NetSpawnedObject1.NetworkObjectId}!"); - var clientInstance = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[m_NetSpawnedObject1.NetworkObjectId]; - Assert.True(clientInstance.HasAuthority, $"Client-{m_ClientNetworkManagers[0].LocalClientId} does not have authority to hide NetworkObject ID: {m_NetSpawnedObject1.NetworkObjectId}!"); - clientInstance.NetworkShow(m_ClientNetworkManagers[1].LocalClientId); - } - else - { - m_NetSpawnedObject1.NetworkShow(m_ClientNetworkManagers[1].LocalClientId); - } - - yield return WaitForConditionOrTimeOut(() => ShowHideObject.ClientTargetedNetworkObjects.Count == 1); - - Assert.True(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId == m_ClientNetworkManagers[0].LocalClientId); - } - - private bool AllClientsSpawnedObject1() - { - foreach (var client in m_ClientNetworkManagers) - { - if (!ShowHideObject.ObjectsPerClientId.ContainsKey(client.LocalClientId)) - { - return false; - } - } - return true; - } - - [UnityTest] - public IEnumerator NetworkHideChangeOwnershipNotHidden() - { - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ObjectsPerClientId.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientNetworkManagers[1].LocalClientId; - ShowHideObject.Silent = true; - - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - - yield return WaitForConditionOrTimeOut(AllClientsSpawnedObject1); - AssertOnTimeout($"Timed out waiting for all clients to spawn {spawnedObject1.name}!"); - - // change the value - m_NetSpawnedObject1.GetComponent().MyOwnerReadNetworkVariable.Value++; - - // wait for three ticks - yield return WaitForTicks(m_ServerNetworkManager, 3); - - // check we'll actually be changing owners - Assert.False(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId == m_ClientNetworkManagers[0].LocalClientId); - - // only check for value change on one specific client - ShowHideObject.NetworkManagerOfInterest = m_ClientNetworkManagers[0]; - - // change ownership - m_NetSpawnedObject1.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - // wait three ticks - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - - // verify ownership changed - Assert.AreEqual(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId, m_ClientNetworkManagers[0].LocalClientId); - - // verify the expected client got the OnValueChanged. (Only client 1 sets this value) - Assert.AreEqual(1, ShowHideObject.ValueAfterOwnershipChange); - } - - private string Display(NetworkList list) - { - string message = ""; - foreach (var i in list) - { - message += $"{i}, "; - } - - return message; - } - - private void Compare(NetworkList list1, NetworkList list2) - { - if (list1.Count != list2.Count) - { - string message = $"{Display(list1)} versus {Display(list2)}"; - Debug.Log(message); - } - else - { - for (var i = 0; i < list1.Count; i++) - { - if (list1[i] != list2[i]) - { - string message = $"{Display(list1)} versus {Display(list2)}"; - Debug.Log(message); - break; - } - } - } - - Debug.Assert(list1.Count == list2.Count); - } - - private IEnumerator HideThenShowAndHideThenModifyAndShow() - { - VerboseDebug("Hiding"); - // hide - m_NetSpawnedObject1.NetworkHide(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - - VerboseDebug("Showing and Hiding"); - // show and hide - m_NetSpawnedObject1.NetworkShow(1); - m_NetSpawnedObject1.NetworkHide(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - - VerboseDebug("Modifying and Showing"); - // modify and show - m_NetSpawnedObject1.GetComponent().MyList.Add(5); - m_NetSpawnedObject1.NetworkShow(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - } - - - private IEnumerator HideThenModifyAndShow() - { - // hide - m_NetSpawnedObject1.NetworkHide(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - - // modify - m_NetSpawnedObject1.GetComponent().MyList.Add(5); - // show - m_NetSpawnedObject1.NetworkShow(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - - } - - private IEnumerator HideThenShowAndModify() - { - // hide - m_NetSpawnedObject1.NetworkHide(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - - // show - m_NetSpawnedObject1.NetworkShow(1); - // modify - m_NetSpawnedObject1.GetComponent().MyList.Add(5); - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - } - - private IEnumerator HideThenShowAndRPC() - { - // hide - m_NetSpawnedObject1.NetworkHide(1); - yield return WaitForTicks(m_ServerNetworkManager, 3); - - // show - m_NetSpawnedObject1.NetworkShow(1); - m_NetSpawnedObject1.GetComponent().TriggerRpc(); - yield return WaitForTicks(m_ServerNetworkManager, 3); - } - - [UnityTest] - public IEnumerator NetworkShowHideAroundListModify() - { - ShowHideObject.ClientTargetedNetworkObjects.Clear(); - ShowHideObject.ClientIdToTarget = m_ClientNetworkManagers[1].LocalClientId; - ShowHideObject.Silent = true; - - var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager); - m_NetSpawnedObject1 = spawnedObject1.GetComponent(); - - // wait for host to have spawned and gained ownership - while (ShowHideObject.GainOwnershipCount == 0) - { - yield return new WaitForSeconds(0.0f); - } - - for (int i = 0; i < 4; i++) - { - // wait for three ticks - yield return WaitForTicks(m_ServerNetworkManager, 3); - yield return WaitForTicks(m_ClientNetworkManagers[0], 3); - - switch (i) - { - case 0: - VerboseDebug("Running HideThenModifyAndShow"); - yield return HideThenModifyAndShow(); - break; - case 1: - VerboseDebug("Running HideThenShowAndModify"); - yield return HideThenShowAndModify(); - break; - case 2: - VerboseDebug("Running HideThenShowAndHideThenModifyAndShow"); - yield return HideThenShowAndHideThenModifyAndShow(); - break; - case 3: - VerboseDebug("Running HideThenShowAndRPC"); - ShowHideObject.ClientIdsRpcCalledOn = new List(); - yield return HideThenShowAndRPC(); - // Provide enough time for slower systems or VM systems possibly under a heavy load could fail on this test - yield return WaitForConditionOrTimeOut(() => ShowHideObject.ClientIdsRpcCalledOn.Count == NumberOfClients + 1); - AssertOnTimeout($"Timed out waiting for ClientIdsRpcCalledOn.Count ({ShowHideObject.ClientIdsRpcCalledOn.Count}) to equal ({NumberOfClients + 1})!"); - break; - - } - - Compare(ShowHideObject.ObjectsPerClientId[0].MyList, ShowHideObject.ObjectsPerClientId[1].MyList); - Compare(ShowHideObject.ObjectsPerClientId[0].MyList, ShowHideObject.ObjectsPerClientId[2].MyList); - } - } - } -} diff --git a/Tests/Runtime/NetworkShowHideTests.cs.meta b/Tests/Runtime/NetworkShowHideTests.cs.meta deleted file mode 100644 index 8550a0f..0000000 --- a/Tests/Runtime/NetworkShowHideTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bad53d2f164c74c46a55fa2ccb1f9b57 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkSpawnManagerTests.cs b/Tests/Runtime/NetworkSpawnManagerTests.cs deleted file mode 100644 index 7835bfe..0000000 --- a/Tests/Runtime/NetworkSpawnManagerTests.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - internal class NetworkSpawnManagerTests : NetcodeIntegrationTest - { - private ulong serverSideClientId => NetworkManager.ServerClientId; - private ulong clientSideClientId => m_ClientNetworkManagers[0].LocalClientId; - private ulong otherClientSideClientId => m_ClientNetworkManagers[1].LocalClientId; - - protected override int NumberOfClients => 2; - - public NetworkSpawnManagerTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - [Test] - public void TestServerCanAccessItsOwnPlayer() - { - // server can access its own player - var serverSideServerPlayerObject = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(serverSideClientId); - Assert.NotNull(serverSideServerPlayerObject); - Assert.AreEqual(serverSideClientId, serverSideServerPlayerObject.OwnerClientId); - } - - - /// - /// Test was converted from a Test to UnityTest so distributed authority mode will pass this test. - /// In distributed authority mode, client-side player spawning is enabled by default which requires - /// all client (including DAHost) instances to wait for all players to be spawned. - /// - [UnityTest] - public IEnumerator TestServerCanAccessOtherPlayers() - { - yield return null; - // server can access other players - var serverSideClientPlayerObject = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(clientSideClientId); - Assert.NotNull(serverSideClientPlayerObject); - Assert.AreEqual(clientSideClientId, serverSideClientPlayerObject.OwnerClientId); - - var serverSideOtherClientPlayerObject = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(otherClientSideClientId); - Assert.NotNull(serverSideOtherClientPlayerObject); - Assert.AreEqual(otherClientSideClientId, serverSideOtherClientPlayerObject.OwnerClientId); - - } - - [Test] - public void TestClientCantAccessServerPlayer() - { - if (m_DistributedAuthority) - { - VerboseDebug($"Ignoring test: Clients have access to other player objects in {m_NetworkTopologyType} mode."); - return; - } - // client can't access server player - Assert.Throws(() => - { - m_ClientNetworkManagers[0].SpawnManager.GetPlayerNetworkObject(serverSideClientId); - }); - } - - [Test] - public void TestClientCanAccessOwnPlayer() - { - // client can access own player - var clientSideClientPlayerObject = m_ClientNetworkManagers[0].SpawnManager.GetPlayerNetworkObject(clientSideClientId); - Assert.NotNull(clientSideClientPlayerObject); - Assert.AreEqual(clientSideClientId, clientSideClientPlayerObject.OwnerClientId); - } - - [Test] - public void TestClientCanAccessOtherPlayer() - { - - if (!m_DistributedAuthority) - { - VerboseDebug($"Ignoring test: Clients do not have access to other player objects in {m_NetworkTopologyType} mode."); - return; - } - - var otherClientPlayer = m_ClientNetworkManagers[0].SpawnManager.GetPlayerNetworkObject(otherClientSideClientId); - Assert.NotNull(otherClientPlayer, $"Failed to obtain Client{otherClientSideClientId}'s player object!"); - } - - [Test] - public void TestClientCantAccessOtherPlayer() - { - if (m_DistributedAuthority) - { - VerboseDebug($"Ignoring test: Clients have access to other player objects in {m_NetworkTopologyType} mode."); - return; - } - - // client can't access other player - Assert.Throws(() => - { - m_ClientNetworkManagers[0].SpawnManager.GetPlayerNetworkObject(otherClientSideClientId); - }); - } - - [Test] - public void TestServerGetsNullValueIfInvalidId() - { - // server gets null value if invalid id - var nullPlayer = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(9999); - Assert.Null(nullPlayer); - } - - [Test] - public void TestServerCanUseGetLocalPlayerObject() - { - // test server can use GetLocalPlayerObject - var serverSideServerPlayerObject = m_ServerNetworkManager.SpawnManager.GetLocalPlayerObject(); - Assert.NotNull(serverSideServerPlayerObject); - Assert.AreEqual(serverSideClientId, serverSideServerPlayerObject.OwnerClientId); - } - - [Test] - public void TestClientCanUseGetLocalPlayerObject() - { - // test client can use GetLocalPlayerObject - var clientSideClientPlayerObject = m_ClientNetworkManagers[0].SpawnManager.GetLocalPlayerObject(); - Assert.NotNull(clientSideClientPlayerObject); - Assert.AreEqual(clientSideClientId, clientSideClientPlayerObject.OwnerClientId); - } - - private bool m_ClientDisconnected; - - [UnityTest] - public IEnumerator TestConnectAndDisconnect() - { - // test when client connects, player object is now available - yield return CreateAndStartNewClient(); - var newClientNetworkManager = m_ClientNetworkManagers[NumberOfClients]; - var newClientLocalClientId = newClientNetworkManager.LocalClientId; - - // test new client can get that itself locally - var newPlayerObject = newClientNetworkManager.SpawnManager.GetLocalPlayerObject(); - Assert.NotNull(newPlayerObject); - Assert.AreEqual(newClientLocalClientId, newPlayerObject.OwnerClientId); - // test server can get that new client locally - var serverSideNewClientPlayer = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(newClientLocalClientId); - Assert.NotNull(serverSideNewClientPlayer); - Assert.AreEqual(newClientLocalClientId, serverSideNewClientPlayer.OwnerClientId); - - // test when client disconnects, player object no longer available. - var nbConnectedClients = m_ServerNetworkManager.ConnectedClients.Count; - m_ClientDisconnected = false; - newClientNetworkManager.OnClientDisconnectCallback += ClientNetworkManager_OnClientDisconnectCallback; - m_ServerNetworkManager.DisconnectClient(newClientLocalClientId); - yield return WaitForConditionOrTimeOut(() => m_ClientDisconnected); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client to disconnect"); - // Call this to clean up NetcodeIntegrationTestHelpers - NetcodeIntegrationTestHelpers.StopOneClient(newClientNetworkManager); - - Assert.AreEqual(m_ServerNetworkManager.ConnectedClients.Count, nbConnectedClients - 1); - serverSideNewClientPlayer = m_ServerNetworkManager.SpawnManager.GetPlayerNetworkObject(newClientLocalClientId); - Assert.Null(serverSideNewClientPlayer); - } - - private void ClientNetworkManager_OnClientDisconnectCallback(ulong obj) - { - m_ClientDisconnected = true; - } - } -} diff --git a/Tests/Runtime/NetworkSpawnManagerTests.cs.meta b/Tests/Runtime/NetworkSpawnManagerTests.cs.meta deleted file mode 100644 index 88c0a11..0000000 --- a/Tests/Runtime/NetworkSpawnManagerTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 173bed02aed54db4a4f056c245a67393 -timeCreated: 1621449221 \ No newline at end of file diff --git a/Tests/Runtime/NetworkTransform.meta b/Tests/Runtime/NetworkTransform.meta deleted file mode 100644 index 5d61983..0000000 --- a/Tests/Runtime/NetworkTransform.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7b88072d3918a44268b5ed6910f6324e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs b/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs deleted file mode 100644 index 4413b73..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs +++ /dev/null @@ -1,1042 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkTransformBase : IntegrationTestWithApproximation - { - - // The number of iterations to change position, rotation, and scale for NetworkTransformMultipleChangesOverTime - protected const int k_PositionRotationScaleIterations = 3; - protected const int k_PositionRotationScaleIterations3Axis = 8; - - protected float m_CurrentHalfPrecision = 0.0f; - protected const float k_HalfPrecisionPosScale = 0.1256f; - protected const float k_HalfPrecisionRot = 0.725f; - - - protected NetworkObject m_AuthoritativePlayer; - protected NetworkObject m_NonAuthoritativePlayer; - protected NetworkObject m_ChildObject; - protected NetworkObject m_SubChildObject; - protected NetworkObject m_ParentObject; - - protected NetworkTransformTestComponent m_AuthoritativeTransform; - protected NetworkTransformTestComponent m_NonAuthoritativeTransform; - protected NetworkTransformTestComponent m_OwnerTransform; - - - protected int m_OriginalTargetFrameRate; - protected Axis m_CurrentAxis; - protected bool m_AxisExcluded; - protected float m_DetectedPotentialInterpolatedTeleport; - - protected StringBuilder m_InfoMessage = new StringBuilder(); - - protected Rotation m_Rotation = Rotation.Euler; - protected Precision m_Precision = Precision.Full; - protected RotationCompression m_RotationCompression = RotationCompression.None; - protected Authority m_Authority; - - // To test that local position, rotation, and scale remain the same when parented. - protected Vector3 m_ChildObjectLocalPosition = new Vector3(5.0f, 0.0f, -5.0f); - protected Vector3 m_ChildObjectLocalRotation = new Vector3(-35.0f, 90.0f, 270.0f); - protected Vector3 m_ChildObjectLocalScale = new Vector3(0.1f, 0.5f, 0.4f); - protected Vector3 m_SubChildObjectLocalPosition = new Vector3(2.0f, 1.0f, -1.0f); - protected Vector3 m_SubChildObjectLocalRotation = new Vector3(5.0f, 15.0f, 124.0f); - protected Vector3 m_SubChildObjectLocalScale = new Vector3(1.0f, 0.15f, 0.75f); - protected NetworkObject m_AuthorityParentObject; - protected NetworkTransformTestComponent m_AuthorityParentNetworkTransform; - protected NetworkObject m_AuthorityChildObject; - protected NetworkObject m_AuthoritySubChildObject; - protected ChildObjectComponent m_AuthorityChildNetworkTransform; - protected ChildObjectComponent m_AuthoritySubChildNetworkTransform; - - public enum Authority - { - ServerAuthority, - OwnerAuthority - } - - public enum Interpolation - { - DisableInterpolate, - EnableInterpolate - } - - public enum Precision - { - Half, - Full - } - - public enum Rotation - { - Euler, - Quaternion - } - - public enum RotationCompression - { - None, - QuaternionCompress - } - - public enum TransformSpace - { - World, - Local - } - - public enum OverrideState - { - Update, - CommitToTransform, - SetState - } - - public enum Axis - { - X, - Y, - Z, - XY, - XZ, - YZ, - XYZ - } - - protected enum ChildrenTransformCheckType - { - Connected_Clients, - Late_Join_Client - } - - protected override int NumberOfClients => OnNumberOfClients(); - - protected override float GetDeltaVarianceThreshold() - { - if (m_Precision == Precision.Half || m_RotationCompression == RotationCompression.QuaternionCompress) - { - return m_CurrentHalfPrecision; - } - return 0.055f; - } - - /// - /// Override to provide the number of clients - /// - /// - protected virtual int OnNumberOfClients() - { - return 1; - } - - /// - /// Determines whether the test will use unreliable delivery for implicit state updates or not - /// - protected virtual bool UseUnreliableDeltas() - { - return false; - } - - protected virtual void Setup() - { - NetworkTransformTestComponent.AuthorityInstance = null; - m_Precision = Precision.Full; - ChildObjectComponent.Reset(); - } - - protected virtual void Teardown() - { - m_EnableVerboseDebug = false; - Object.DestroyImmediate(m_PlayerPrefab); - } - - /// - /// Handles the Setup for time travel enabled child derived tests - /// - protected override void OnInlineSetup() - { - Setup(); - base.OnInlineSetup(); - } - - /// - /// Handles the Teardown for time travel enabled child derived tests - /// - protected override void OnInlineTearDown() - { - Teardown(); - base.OnInlineTearDown(); - } - - /// - /// Handles the Setup for coroutine based derived tests - /// - protected override IEnumerator OnSetup() - { - Setup(); - return base.OnSetup(); - } - - /// - /// Handles the Teardown for coroutine based derived tests - /// - protected override IEnumerator OnTearDown() - { - Teardown(); - return base.OnTearDown(); - } - - /// - /// Constructor - /// - /// Determines if we are running as a server or host - /// Determines if we are using server or owner authority - public NetworkTransformBase(HostOrServer testWithHost, Authority authority, RotationCompression rotationCompression, Rotation rotation, Precision precision) : base(testWithHost) - { - m_Authority = authority; - m_Precision = precision; - m_RotationCompression = rotationCompression; - m_Rotation = rotation; - } - - protected virtual int TargetFrameRate() - { - return 120; - } - - protected override void OnOneTimeSetup() - { - m_OriginalTargetFrameRate = Application.targetFrameRate; - Application.targetFrameRate = TargetFrameRate(); - base.OnOneTimeSetup(); - } - - protected override void OnOneTimeTearDown() - { - Application.targetFrameRate = m_OriginalTargetFrameRate; - base.OnOneTimeTearDown(); - } - - protected override void OnCreatePlayerPrefab() - { - var networkTransformTestComponent = m_PlayerPrefab.AddComponent(); - networkTransformTestComponent.ServerAuthority = m_Authority == Authority.ServerAuthority; - } - - protected override void OnServerAndClientsCreated() - { - var subChildObject = CreateNetworkObjectPrefab("SubChildObject"); - var subChildNetworkTransform = subChildObject.AddComponent(); - subChildNetworkTransform.ServerAuthority = m_Authority == Authority.ServerAuthority; - m_SubChildObject = subChildObject.GetComponent(); - - var childObject = CreateNetworkObjectPrefab("ChildObject"); - var childNetworkTransform = childObject.AddComponent(); - childNetworkTransform.ServerAuthority = m_Authority == Authority.ServerAuthority; - m_ChildObject = childObject.GetComponent(); - - var parentObject = CreateNetworkObjectPrefab("ParentObject"); - var parentNetworkTransform = parentObject.AddComponent(); - parentNetworkTransform.ServerAuthority = m_Authority == Authority.ServerAuthority; - m_ParentObject = parentObject.GetComponent(); - - // Now apply local transform values - m_ChildObject.transform.position = m_ChildObjectLocalPosition; - var childRotation = m_ChildObject.transform.rotation; - childRotation.eulerAngles = m_ChildObjectLocalRotation; - m_ChildObject.transform.rotation = childRotation; - m_ChildObject.transform.localScale = m_ChildObjectLocalScale; - - m_SubChildObject.transform.position = m_SubChildObjectLocalPosition; - var subChildRotation = m_SubChildObject.transform.rotation; - subChildRotation.eulerAngles = m_SubChildObjectLocalRotation; - m_SubChildObject.transform.rotation = childRotation; - m_SubChildObject.transform.localScale = m_SubChildObjectLocalScale; - - if (m_EnableVerboseDebug) - { - m_ServerNetworkManager.LogLevel = LogLevel.Developer; - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - clientNetworkManager.LogLevel = LogLevel.Developer; - } - } - - m_ServerNetworkManager.NetworkConfig.TickRate = GetTickRate(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - clientNetworkManager.NetworkConfig.TickRate = GetTickRate(); - } - } - - - protected virtual void OnClientsAndServerConnectedSetup() - { - // Get the client player representation on both the server and the client side - var serverSideClientPlayer = m_PlayerNetworkObjects[0][m_ClientNetworkManagers[0].LocalClientId]; - var clientSideClientPlayer = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId]; - - m_AuthoritativePlayer = m_Authority == Authority.ServerAuthority ? serverSideClientPlayer : clientSideClientPlayer; - m_NonAuthoritativePlayer = m_Authority == Authority.ServerAuthority ? clientSideClientPlayer : serverSideClientPlayer; - - // Get the NetworkTransformTestComponent to make sure the client side is ready before starting test - m_AuthoritativeTransform = m_AuthoritativePlayer.GetComponent(); - m_NonAuthoritativeTransform = m_NonAuthoritativePlayer.GetComponent(); - - // Setup whether we are or are not using unreliable deltas - m_AuthoritativeTransform.UseUnreliableDeltas = UseUnreliableDeltas(); - m_NonAuthoritativeTransform.UseUnreliableDeltas = UseUnreliableDeltas(); - - m_AuthoritativeTransform.UseHalfFloatPrecision = m_Precision == Precision.Half; - m_AuthoritativeTransform.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - m_AuthoritativeTransform.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - m_NonAuthoritativeTransform.UseHalfFloatPrecision = m_Precision == Precision.Half; - m_NonAuthoritativeTransform.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - m_NonAuthoritativeTransform.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - - m_OwnerTransform = m_AuthoritativeTransform.IsOwner ? m_AuthoritativeTransform : m_NonAuthoritativeTransform; - } - - protected override void OnTimeTravelServerAndClientsConnected() - { - OnClientsAndServerConnectedSetup(); - - // Wait for the client-side to notify it is finished initializing and spawning. - var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_NonAuthoritativeTransform.ReadyToReceivePositionUpdate == true); - Assert.True(success, "Timed out waiting for client-side to notify it is ready!"); - - Assert.True(m_AuthoritativeTransform.CanCommitToTransform); - Assert.False(m_NonAuthoritativeTransform.CanCommitToTransform); - // Just wait for at least one tick for NetworkTransforms to finish synchronization - TimeTravelAdvanceTick(); - } - - /// - /// Handles the OnServerAndClientsConnected for coroutine based derived tests - /// - protected override IEnumerator OnServerAndClientsConnected() - { - // Wait for the client-side to notify it is finished initializing and spawning. - yield return WaitForClientsConnectedOrTimeOut(); - AssertOnTimeout("Timed out waiting for client-side to notify it is ready!"); - OnClientsAndServerConnectedSetup(); - yield return base.OnServerAndClientsConnected(); - } - - /// - /// Handles setting a new client being connected - /// - protected override void OnNewClientCreated(NetworkManager networkManager) - { - networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs; - networkManager.NetworkConfig.TickRate = GetTickRate(); - if (m_EnableVerboseDebug) - { - networkManager.LogLevel = LogLevel.Developer; - } - base.OnNewClientCreated(networkManager); - } - - - /// - /// Returns true when the server-host and all clients have - /// instantiated the child object to be used in - /// - /// - protected bool AllChildObjectInstancesAreSpawned() - { - if (ChildObjectComponent.AuthorityInstance == null) - { - return false; - } - - if (ChildObjectComponent.HasSubChild && ChildObjectComponent.AuthoritySubInstance == null) - { - return false; - } - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - if (!ChildObjectComponent.ClientInstances.ContainsKey(clientNetworkManager.LocalClientId)) - { - return false; - } - } - return true; - } - - protected bool AllFirstLevelChildObjectInstancesHaveChild() - { - foreach (var instance in ChildObjectComponent.ClientInstances.Values) - { - if (instance.transform.parent == null) - { - return false; - } - } - return true; - } - - protected bool AllChildObjectInstancesHaveChild() - { - foreach (var instance in ChildObjectComponent.ClientInstances.Values) - { - if (instance.transform.parent == null) - { - return false; - } - } - if (ChildObjectComponent.HasSubChild) - { - foreach (var instance in ChildObjectComponent.ClientSubChildInstances.Values) - { - if (instance.transform.parent == null) - { - return false; - } - } - } - return true; - } - - protected bool AllFirstLevelChildObjectInstancesHaveNoParent() - { - foreach (var instance in ChildObjectComponent.ClientInstances.Values) - { - if (instance.transform.parent != null) - { - return false; - } - } - return true; - } - - protected bool AllSubChildObjectInstancesHaveNoParent() - { - if (ChildObjectComponent.HasSubChild) - { - foreach (var instance in ChildObjectComponent.ClientSubChildInstances.Values) - { - if (instance.transform.parent != null) - { - return false; - } - } - } - return true; - } - - /// - /// A wait condition specific method that assures the local space coordinates - /// are not impacted by NetworkTransform when parented. - /// - protected bool AllInstancesKeptLocalTransformValues(bool useSubChild) - { - var authorityObjectLocalPosition = useSubChild ? m_AuthoritySubChildObject.transform.localPosition : m_AuthorityChildObject.transform.localPosition; - var authorityObjectLocalRotation = useSubChild ? m_AuthoritySubChildObject.transform.localRotation.eulerAngles : m_AuthorityChildObject.transform.localRotation.eulerAngles; - var authorityObjectLocalScale = useSubChild ? m_AuthoritySubChildObject.transform.localScale : m_AuthorityChildObject.transform.localScale; - var instances = useSubChild ? ChildObjectComponent.SubInstances : ChildObjectComponent.Instances; - foreach (var childInstance in instances) - { - var childLocalPosition = childInstance.transform.localPosition; - var childLocalRotation = childInstance.transform.localRotation.eulerAngles; - var childLocalScale = childInstance.transform.localScale; - // Adjust approximation based on precision - if (m_Precision == Precision.Half) - { - m_CurrentHalfPrecision = k_HalfPrecisionPosScale; - } - if (!Approximately(childLocalPosition, authorityObjectLocalPosition)) - { - return false; - } - if (!Approximately(childLocalScale, authorityObjectLocalScale)) - { - return false; - } - // Adjust approximation based on precision - if (m_Precision == Precision.Half || m_RotationCompression == RotationCompression.QuaternionCompress) - { - m_CurrentHalfPrecision = k_HalfPrecisionRot; - } - if (!ApproximatelyEuler(childLocalRotation, authorityObjectLocalRotation)) - { - return false; - } - } - return true; - } - - protected bool PostAllChildrenLocalTransformValuesMatch(bool useSubChild) - { - var success = !s_GlobalTimeoutHelper.TimedOut; - var authorityObjectLocalPosition = useSubChild ? m_AuthoritySubChildObject.transform.localPosition : m_AuthorityChildObject.transform.localPosition; - var authorityObjectLocalRotation = useSubChild ? m_AuthoritySubChildObject.transform.localRotation.eulerAngles : m_AuthorityChildObject.transform.localRotation.eulerAngles; - var authorityObjectLocalScale = useSubChild ? m_AuthoritySubChildObject.transform.localScale : m_AuthorityChildObject.transform.localScale; - - if (s_GlobalTimeoutHelper.TimedOut) - { - // If we timed out, then wait for a full range of ticks (plus 1) to assure it sent synchronization data. - for (int j = 0; j < m_ServerNetworkManager.NetworkConfig.TickRate; j++) - { - var instances = useSubChild ? ChildObjectComponent.SubInstances : ChildObjectComponent.Instances; - foreach (var childInstance in instances) - { - var childParentName = "invalid"; - try - { - childParentName = useSubChild ? childInstance.transform.parent.parent.name : childInstance.transform.name; - } - catch (System.Exception ex) - { - Debug.Log(ex.Message); - } - var childLocalPosition = childInstance.transform.localPosition; - var childLocalRotation = childInstance.transform.localRotation.eulerAngles; - var childLocalScale = childInstance.transform.localScale; - // Adjust approximation based on precision - if (m_Precision == Precision.Half || m_RotationCompression == RotationCompression.QuaternionCompress) - { - m_CurrentHalfPrecision = k_HalfPrecisionPosScale; - } - if (!Approximately(childLocalPosition, authorityObjectLocalPosition)) - { - m_InfoMessage.AppendLine($"[{childParentName}][{childInstance.name}] Child's Local Position ({GetVector3Values(childLocalPosition)}) | Authority Local Position ({GetVector3Values(authorityObjectLocalPosition)})"); - success = false; - } - if (!Approximately(childLocalScale, authorityObjectLocalScale)) - { - m_InfoMessage.AppendLine($"[{childParentName}][{childInstance.name}] Child's Local Scale ({GetVector3Values(childLocalScale)}) | Authority Local Scale ({GetVector3Values(authorityObjectLocalScale)})"); - success = false; - } - - // Adjust approximation based on precision - if (m_Precision == Precision.Half || m_RotationCompression == RotationCompression.QuaternionCompress) - { - m_CurrentHalfPrecision = k_HalfPrecisionRot; - } - if (!ApproximatelyEuler(childLocalRotation, authorityObjectLocalRotation)) - { - m_InfoMessage.AppendLine($"[{childParentName}][{childInstance.name}] Child's Local Rotation ({GetVector3Values(childLocalRotation)}) | Authority Local Rotation ({GetVector3Values(authorityObjectLocalRotation)})"); - success = false; - } - } - } - } - return success; - } - - - - /// - /// Validates that moving, rotating, and scaling the authority side with a single - /// tick will properly synchronize the non-authoritative side with the same values. - /// - protected void MoveRotateAndScaleAuthority(Vector3 position, Vector3 rotation, Vector3 scale, OverrideState overrideState) - { - switch (overrideState) - { - case OverrideState.SetState: - { - var authoritativeRotation = m_AuthoritativeTransform.GetSpaceRelativeRotation(); - authoritativeRotation.eulerAngles = rotation; - if (m_Authority == Authority.OwnerAuthority) - { - // Under the scenario where the owner is not the server, and non-auth is the server we set the state from the server - // to be updated to the owner. - if (m_AuthoritativeTransform.IsOwner && !m_AuthoritativeTransform.IsServer && m_NonAuthoritativeTransform.IsServer) - { - m_NonAuthoritativeTransform.SetState(position, authoritativeRotation, scale); - } - else - { - m_AuthoritativeTransform.SetState(position, authoritativeRotation, scale); - } - } - else - { - m_AuthoritativeTransform.SetState(position, authoritativeRotation, scale); - } - - break; - } - case OverrideState.Update: - default: - { - m_AuthoritativeTransform.transform.position = position; - - var authoritativeRotation = m_AuthoritativeTransform.GetSpaceRelativeRotation(); - authoritativeRotation.eulerAngles = rotation; - m_AuthoritativeTransform.transform.rotation = authoritativeRotation; - m_AuthoritativeTransform.transform.localScale = scale; - break; - } - } - } - - /// - /// Randomly determine if an axis should be excluded. - /// If so, then randomly pick one of the axis to be excluded. - /// - protected Vector3 RandomlyExcludeAxis(Vector3 delta) - { - if (Random.Range(0.0f, 1.0f) >= 0.5f) - { - m_AxisExcluded = true; - var axisToIgnore = Random.Range(0, 2); - switch (axisToIgnore) - { - case 0: - { - delta.x = 0; - break; - } - case 1: - { - delta.y = 0; - break; - } - case 2: - { - delta.z = 0; - break; - } - } - } - return delta; - } - - protected bool PositionRotationScaleMatches() - { - return RotationsMatch() && PositionsMatch() && ScaleValuesMatch(); - } - - protected bool PositionRotationScaleMatches(Vector3 position, Vector3 eulerRotation, Vector3 scale) - { - return PositionsMatchesValue(position) && RotationMatchesValue(eulerRotation) && ScaleMatchesValue(scale); - } - - protected bool PositionsMatchesValue(Vector3 positionToMatch) - { - var authorityPosition = m_AuthoritativeTransform.transform.position; - var nonAuthorityPosition = m_NonAuthoritativeTransform.transform.position; - var auhtorityIsEqual = Approximately(authorityPosition, positionToMatch); - var nonauthorityIsEqual = Approximately(nonAuthorityPosition, positionToMatch); - - if (!auhtorityIsEqual) - { - VerboseDebug($"Authority position {authorityPosition} != position to match: {positionToMatch}!"); - } - if (!nonauthorityIsEqual) - { - VerboseDebug($"NonAuthority position {nonAuthorityPosition} != position to match: {positionToMatch}!"); - } - return auhtorityIsEqual && nonauthorityIsEqual; - } - - protected bool RotationMatchesValue(Vector3 rotationEulerToMatch) - { - var authorityRotationEuler = m_AuthoritativeTransform.transform.rotation.eulerAngles; - var nonAuthorityRotationEuler = m_NonAuthoritativeTransform.transform.rotation.eulerAngles; - var auhtorityIsEqual = Approximately(authorityRotationEuler, rotationEulerToMatch); - var nonauthorityIsEqual = Approximately(nonAuthorityRotationEuler, rotationEulerToMatch); - - if (!auhtorityIsEqual) - { - VerboseDebug($"Authority rotation {authorityRotationEuler} != rotation to match: {rotationEulerToMatch}!"); - } - if (!nonauthorityIsEqual) - { - VerboseDebug($"NonAuthority rotation {nonAuthorityRotationEuler} != rotation to match: {rotationEulerToMatch}!"); - } - return auhtorityIsEqual && nonauthorityIsEqual; - } - - protected bool ScaleMatchesValue(Vector3 scaleToMatch) - { - var authorityScale = m_AuthoritativeTransform.transform.localScale; - var nonAuthorityScale = m_NonAuthoritativeTransform.transform.localScale; - var auhtorityIsEqual = Approximately(authorityScale, scaleToMatch); - var nonauthorityIsEqual = Approximately(nonAuthorityScale, scaleToMatch); - - if (!auhtorityIsEqual) - { - VerboseDebug($"Authority scale {authorityScale} != scale to match: {scaleToMatch}!"); - } - if (!nonauthorityIsEqual) - { - VerboseDebug($"NonAuthority scale {nonAuthorityScale} != scale to match: {scaleToMatch}!"); - } - return auhtorityIsEqual && nonauthorityIsEqual; - } - - protected bool TeleportPositionMatches(Vector3 nonAuthorityOriginalPosition) - { - var nonAuthorityPosition = m_NonAuthoritativeTransform.transform.position; - var authorityPosition = m_AuthoritativeTransform.transform.position; - var targetDistance = Mathf.Abs(Vector3.Distance(nonAuthorityOriginalPosition, authorityPosition)); - var nonAuthorityCurrentDistance = Mathf.Abs(Vector3.Distance(nonAuthorityPosition, nonAuthorityOriginalPosition)); - // If we are not within our target distance range - if (!Approximately(targetDistance, nonAuthorityCurrentDistance)) - { - // Apply the non-authority's distance that is checked at the end of the teleport test - m_DetectedPotentialInterpolatedTeleport = nonAuthorityCurrentDistance; - return false; - } - else - { - // Otherwise, if we are within our target distance range then reset any already set value - m_DetectedPotentialInterpolatedTeleport = 0.0f; - } - var xIsEqual = Approximately(authorityPosition.x, nonAuthorityPosition.x); - var yIsEqual = Approximately(authorityPosition.y, nonAuthorityPosition.y); - var zIsEqual = Approximately(authorityPosition.z, nonAuthorityPosition.z); - if (!xIsEqual || !yIsEqual || !zIsEqual) - { - VerboseDebug($"[{m_AuthoritativeTransform.gameObject.name}] Authority position {authorityPosition} != [{m_NonAuthoritativeTransform.gameObject.name}] NonAuthority position {nonAuthorityPosition}"); - } - return xIsEqual && yIsEqual && zIsEqual; - } - - protected bool RotationsMatch(bool printDeltas = false) - { - m_CurrentHalfPrecision = k_HalfPrecisionRot; - var authorityEulerRotation = m_AuthoritativeTransform.GetSpaceRelativeRotation().eulerAngles; - var nonAuthorityEulerRotation = m_NonAuthoritativeTransform.GetSpaceRelativeRotation().eulerAngles; - var xIsEqual = ApproximatelyEuler(authorityEulerRotation.x, nonAuthorityEulerRotation.x) || !m_AuthoritativeTransform.SyncRotAngleX; - var yIsEqual = ApproximatelyEuler(authorityEulerRotation.y, nonAuthorityEulerRotation.y) || !m_AuthoritativeTransform.SyncRotAngleY; - var zIsEqual = ApproximatelyEuler(authorityEulerRotation.z, nonAuthorityEulerRotation.z) || !m_AuthoritativeTransform.SyncRotAngleZ; - if (!xIsEqual || !yIsEqual || !zIsEqual) - { - VerboseDebug($"[{m_AuthoritativeTransform.gameObject.name}][X-{xIsEqual} | Y-{yIsEqual} | Z-{zIsEqual}][{m_CurrentAxis}]" + - $"[Sync: X-{m_AuthoritativeTransform.SyncRotAngleX} | Y-{m_AuthoritativeTransform.SyncRotAngleY} | Z-{m_AuthoritativeTransform.SyncRotAngleZ}] Authority rotation {authorityEulerRotation} != [{m_NonAuthoritativeTransform.gameObject.name}] NonAuthority rotation {nonAuthorityEulerRotation}"); - } - if (printDeltas) - { - Debug.Log($"[Rotation Match] Euler Delta {EulerDelta(authorityEulerRotation, nonAuthorityEulerRotation)}"); - } - return xIsEqual && yIsEqual && zIsEqual; - } - - protected bool PositionsMatch(bool printDeltas = false) - { - m_CurrentHalfPrecision = k_HalfPrecisionPosScale; - var authorityPosition = m_AuthoritativeTransform.GetSpaceRelativePosition(); - var nonAuthorityPosition = m_NonAuthoritativeTransform.GetSpaceRelativePosition(); - var xIsEqual = Approximately(authorityPosition.x, nonAuthorityPosition.x) || !m_AuthoritativeTransform.SyncPositionX; - var yIsEqual = Approximately(authorityPosition.y, nonAuthorityPosition.y) || !m_AuthoritativeTransform.SyncPositionY; - var zIsEqual = Approximately(authorityPosition.z, nonAuthorityPosition.z) || !m_AuthoritativeTransform.SyncPositionZ; - if (!xIsEqual || !yIsEqual || !zIsEqual) - { - VerboseDebug($"[{m_AuthoritativeTransform.gameObject.name}] Authority position {authorityPosition} != [{m_NonAuthoritativeTransform.gameObject.name}] NonAuthority position {nonAuthorityPosition}"); - } - return xIsEqual && yIsEqual && zIsEqual; - } - - protected bool ScaleValuesMatch(bool printDeltas = false) - { - m_CurrentHalfPrecision = k_HalfPrecisionPosScale; - var authorityScale = m_AuthoritativeTransform.transform.localScale; - var nonAuthorityScale = m_NonAuthoritativeTransform.transform.localScale; - var xIsEqual = Approximately(authorityScale.x, nonAuthorityScale.x) || !m_AuthoritativeTransform.SyncScaleX; - var yIsEqual = Approximately(authorityScale.y, nonAuthorityScale.y) || !m_AuthoritativeTransform.SyncScaleY; - var zIsEqual = Approximately(authorityScale.z, nonAuthorityScale.z) || !m_AuthoritativeTransform.SyncScaleZ; - if (!xIsEqual || !yIsEqual || !zIsEqual) - { - VerboseDebug($"[{m_AuthoritativeTransform.gameObject.name}] Authority scale {authorityScale} != [{m_NonAuthoritativeTransform.gameObject.name}] NonAuthority scale {nonAuthorityScale}"); - } - return xIsEqual && yIsEqual && zIsEqual; - } - - private void PrintPositionRotationScaleDeltas() - { - RotationsMatch(true); - PositionsMatch(true); - ScaleValuesMatch(true); - } - } - - /// - /// Helper component for all NetworkTransformTests - /// - internal class NetworkTransformTestComponent : NetworkTransform - { - public bool ServerAuthority; - public bool ReadyToReceivePositionUpdate = false; - - public NetworkTransformState AuthorityLastSentState; - public bool StatePushed { get; internal set; } - - public delegate void AuthorityPushedTransformStateDelegateHandler(ref NetworkTransformState networkTransformState); - - public event AuthorityPushedTransformStateDelegateHandler AuthorityPushedTransformState; - - protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) - { - StatePushed = true; - AuthorityLastSentState = networkTransformState; - AuthorityPushedTransformState?.Invoke(ref networkTransformState); - base.OnAuthorityPushTransformState(ref networkTransformState); - } - - - public bool StateUpdated { get; internal set; } - protected override void OnNetworkTransformStateUpdated(ref NetworkTransformState oldState, ref NetworkTransformState newState) - { - StateUpdated = true; - base.OnNetworkTransformStateUpdated(ref oldState, ref newState); - } - - protected override bool OnIsServerAuthoritative() - { - return ServerAuthority; - } - - public static NetworkTransformTestComponent AuthorityInstance; - - public override void OnNetworkSpawn() - { - base.OnNetworkSpawn(); - - if (CanCommitToTransform) - { - AuthorityInstance = this; - } - - ReadyToReceivePositionUpdate = true; - } - - public void CommitToTransform() - { - TryCommitTransformToServer(transform, NetworkManager.LocalTime.Time); - } - - public (bool isDirty, bool isPositionDirty, bool isRotationDirty, bool isScaleDirty) ApplyState() - { - var transformState = ApplyLocalNetworkState(transform); - return (transformState.IsDirty, transformState.HasPositionChange, transformState.HasRotAngleChange, transformState.HasScaleChange); - } - } - - /// - /// Helper component for NetworkTransform parenting tests when - /// a child is a parent of another child (i.e. "sub child") - /// - internal class SubChildObjectComponent : ChildObjectComponent - { - protected override bool IsSubChild() - { - return true; - } - } - - /// - /// Helper component for NetworkTransform parenting tests - /// - internal class ChildObjectComponent : NetworkTransform - { - public static int TestCount; - public static bool EnableChildLog; - public static readonly List Instances = new List(); - public static readonly List SubInstances = new List(); - public static ChildObjectComponent AuthorityInstance { get; internal set; } - public static ChildObjectComponent AuthoritySubInstance { get; internal set; } - public static readonly Dictionary ClientInstances = new Dictionary(); - public static readonly Dictionary ClientSubChildInstances = new Dictionary(); - - public static readonly List InstancesWithLogging = new List(); - - public static bool HasSubChild; - - private StringBuilder m_ChildTransformLog = new StringBuilder(); - private StringBuilder m_ChildStateLog = new StringBuilder(); - - public static void Reset() - { - AuthorityInstance = null; - AuthoritySubInstance = null; - HasSubChild = false; - ClientInstances.Clear(); - ClientSubChildInstances.Clear(); - Instances.Clear(); - SubInstances.Clear(); - } - - public bool ServerAuthority; - - protected virtual bool IsSubChild() - { - return false; - } - - protected override bool OnIsServerAuthoritative() - { - return ServerAuthority; - } - - public override void OnNetworkSpawn() - { - LogTransform(); - - base.OnNetworkSpawn(); - - LogTransform(); - if (CanCommitToTransform) - { - if (!IsSubChild()) - { - AuthorityInstance = this; - } - else - { - AuthoritySubInstance = this; - } - } - else - { - if (!IsSubChild()) - { - Instances.Add(this); - } - else - { - SubInstances.Add(this); - } - } - if (HasSubChild && IsSubChild()) - { - ClientSubChildInstances.Add(NetworkManager.LocalClientId, NetworkObject); - } - else - { - ClientInstances.Add(NetworkManager.LocalClientId, NetworkObject); - } - } - - public override void OnNetworkDespawn() - { - LogToConsole(); - base.OnNetworkDespawn(); - } - - public override void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) - { - base.OnNetworkObjectParentChanged(parentNetworkObject); - - LogTransform(); - } - - protected override void OnAuthorityPushTransformState(ref NetworkTransformState networkTransformState) - { - base.OnAuthorityPushTransformState(ref networkTransformState); - - LogState(ref networkTransformState, true); - } - - protected override void OnNetworkTransformStateUpdated(ref NetworkTransformState oldState, ref NetworkTransformState newState) - { - base.OnNetworkTransformStateUpdated(ref oldState, ref newState); - LogState(ref newState, false); - } - - protected override void OnSynchronize(ref BufferSerializer serializer) - { - base.OnSynchronize(ref serializer); - var localState = SynchronizeState; - LogState(ref localState, serializer.IsWriter); - } - - private void LogTransform() - { - if (!EnableChildLog) - { - return; - } - if (m_ChildTransformLog.Length == 0) - { - m_ChildTransformLog.AppendLine($"[{TestCount}][{name}] Begin Child Transform Log (Authority: {CanCommitToTransform})-------------->"); - } - m_ChildTransformLog.AppendLine($"POS-SR:{GetSpaceRelativePosition()} POS-W: {transform.position} POS-L: {transform.position}"); - m_ChildTransformLog.AppendLine($"SCA-SR:{GetScale()} SCA-LS: {transform.lossyScale} SCA-L: {transform.localScale}"); - } - - private void LogState(ref NetworkTransformState state, bool isPush) - { - if (!EnableChildLog) - { - return; - } - if (m_ChildStateLog.Length == 0) - { - m_ChildStateLog.AppendLine($"[{TestCount}][{name}] Begin Child State Log (Authority: {CanCommitToTransform})-------------->"); - } - var tick = 0; - if (NetworkManager != null && !NetworkManager.ShutdownInProgress) - { - tick = NetworkManager.ServerTime.Tick; - } - - m_ChildStateLog.AppendLine($"[{state.NetworkTick}][{tick}] Tele:{state.IsTeleportingNextFrame} Sync: {state.IsSynchronizing} Reliable: {state.IsReliableStateUpdate()} IsParented: {state.IsParented} HasPos: {state.HasPositionChange} Pos: {state.GetPosition()}"); - m_ChildStateLog.AppendLine($"Lossy:{state.LossyScale} Scale: {state.GetScale()} Rotation: {state.GetRotation()}"); - } - - private void LogToConsole() - { - if (!EnableChildLog) - { - return; - } - LogBuilder(m_ChildTransformLog); - LogBuilder(m_ChildStateLog); - } - - private void LogBuilder(StringBuilder builder) - { - if (builder.Length == 0) - { - return; - } - var contents = builder.ToString(); - var lines = contents.Split('\n'); - if (lines.Length > 45) - { - var count = 0; - var tempBuilder = new StringBuilder(); - - for (int i = 0; i < lines.Length; i++) - { - if ((i % 45) == 0) - { - if (count > 0) - { - Debug.Log(tempBuilder.ToString()); - tempBuilder.Clear(); - } - tempBuilder.AppendLine($"{count}{lines[i]}"); - count++; - } - else - { - tempBuilder.AppendLine($"{lines[i]}"); - } - } - } - else - { - Debug.Log(builder.ToString()); - } - } - } - - -} // Unity.Netcode.RuntimeTests diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs.meta deleted file mode 100644 index 2ffb799..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ccdf46d0c73f8ac47921ec1be2772fac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs b/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs deleted file mode 100644 index 3a7d0be..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs +++ /dev/null @@ -1,314 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.Components; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority)] - internal class NetworkTransformGeneral : NetworkTransformBase - { - public NetworkTransformGeneral(HostOrServer testWithHost, Authority authority) : - base(testWithHost, authority, RotationCompression.None, Rotation.Euler, Precision.Full) - { } - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - /// - /// Test to verify nonAuthority cannot change the transform directly - /// - [Test] - public void VerifyNonAuthorityCantChangeTransform([Values] Interpolation interpolation) - { - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - Assert.AreEqual(Vector3.zero, m_NonAuthoritativeTransform.transform.position, "other side pos should be zero at first"); // sanity check - - m_NonAuthoritativeTransform.transform.position = new Vector3(4, 5, 6); - - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - Assert.AreEqual(Vector3.zero, m_NonAuthoritativeTransform.transform.position, "[Position] NonAuthority was able to change the position!"); - - var nonAuthorityRotation = m_NonAuthoritativeTransform.transform.rotation; - var originalNonAuthorityEulerRotation = nonAuthorityRotation.eulerAngles; - var nonAuthorityEulerRotation = originalNonAuthorityEulerRotation; - // Verify rotation is not marked dirty when rotated by half of the threshold - nonAuthorityEulerRotation.y += 20.0f; - nonAuthorityRotation.eulerAngles = nonAuthorityEulerRotation; - m_NonAuthoritativeTransform.transform.rotation = nonAuthorityRotation; - TimeTravelAdvanceTick(); - var nonAuthorityCurrentEuler = m_NonAuthoritativeTransform.transform.rotation.eulerAngles; - Assert.True(originalNonAuthorityEulerRotation.Equals(nonAuthorityCurrentEuler), "[Rotation] NonAuthority was able to change the rotation!"); - - var nonAuthorityScale = m_NonAuthoritativeTransform.transform.localScale; - m_NonAuthoritativeTransform.transform.localScale = nonAuthorityScale * 100; - - TimeTravelAdvanceTick(); - - Assert.True(nonAuthorityScale.Equals(m_NonAuthoritativeTransform.transform.localScale), "[Scale] NonAuthority was able to change the scale!"); - } - - /// - /// Validates that rotation checks don't produce false positive - /// results when rolling over between 0 and 360 degrees - /// - [Test] - public void TestRotationThresholdDeltaCheck([Values] Interpolation interpolation) - { - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.RotAngleThreshold = m_AuthoritativeTransform.RotAngleThreshold = 5.0f; - var halfThreshold = m_AuthoritativeTransform.RotAngleThreshold * 0.5001f; - - // Apply the current state prior to getting reference rotations which assures we have - // applied the most current rotation deltas and that all bitset flags are updated - var results = m_AuthoritativeTransform.ApplyState(); - TimeTravelAdvanceTick(); - - // Get the current rotation values; - var authorityRotation = m_AuthoritativeTransform.transform.rotation; - var authorityEulerRotation = authorityRotation.eulerAngles; - - // Verify rotation is not marked dirty when rotated by half of the threshold - authorityEulerRotation.y += halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {m_AuthoritativeTransform.RotAngleThreshold} degrees and only adjusted by {halfThreshold} degrees!"); - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // Verify rotation is marked dirty when rotated by another half threshold value - authorityEulerRotation.y += halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by the threshold value: {m_AuthoritativeTransform.RotAngleThreshold} degrees!"); - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - //Reset rotation back to zero on all axis - authorityRotation.eulerAngles = authorityEulerRotation = Vector3.zero; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // Rotate by 360 minus halfThreshold (which is really just negative halfThreshold) and verify rotation is not marked dirty - authorityEulerRotation.y = 360 - halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {m_AuthoritativeTransform.RotAngleThreshold} degrees and only adjusted by " + - $"{Mathf.DeltaAngle(0, authorityEulerRotation.y)} degrees!"); - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // Now apply one more minor decrement that should trigger a dirty flag - authorityEulerRotation.y -= halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by {Mathf.DeltaAngle(0, authorityEulerRotation.y)} degrees!"); - - //Reset rotation back to zero on all axis - authorityRotation.eulerAngles = authorityEulerRotation = Vector3.zero; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // Minor decrement again under the threshold value - authorityEulerRotation.y -= halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsFalse(results.isRotationDirty, $"Rotation is dirty when rotation threshold is {m_AuthoritativeTransform.RotAngleThreshold} degrees and only adjusted by " + - $"{Mathf.DeltaAngle(0, authorityEulerRotation.y)} degrees!"); - // Now allow the delta state to be processed and sent (just allow for two ticks to cover edge cases with time travel and the testing environment) - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // Now decrement another half threshold which should trigger the dirty flag - authorityEulerRotation.y -= halfThreshold; - authorityRotation.eulerAngles = authorityEulerRotation; - m_AuthoritativeTransform.transform.rotation = authorityRotation; - results = m_AuthoritativeTransform.ApplyState(); - Assert.IsTrue(results.isRotationDirty, $"Rotation was not dirty when rotated by {Mathf.DeltaAngle(0, authorityEulerRotation.y)} degrees!"); - } - - private bool ValidateBitSetValues() - { - var serverState = m_AuthoritativeTransform.AuthorityLastSentState; - var clientState = m_NonAuthoritativeTransform.LocalAuthoritativeNetworkState; - if (serverState.HasPositionX == clientState.HasPositionX && serverState.HasPositionY == clientState.HasPositionY && serverState.HasPositionZ == clientState.HasPositionZ && - serverState.HasRotAngleX == clientState.HasRotAngleX && serverState.HasRotAngleY == clientState.HasRotAngleY && serverState.HasRotAngleZ == clientState.HasRotAngleZ && - serverState.HasScaleX == clientState.HasScaleX && serverState.HasScaleY == clientState.HasScaleY && serverState.HasScaleZ == clientState.HasScaleZ) - { - return true; - } - return false; - } - - /// - /// Test to make sure that the bitset value is updated properly - /// - [Test] - public void TestBitsetValue([Values] Interpolation interpolation) - { - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.RotAngleThreshold = m_AuthoritativeTransform.RotAngleThreshold = 0.1f; - m_AuthoritativeTransform.transform.rotation = Quaternion.Euler(1, 2, 3); - TimeTravelAdvanceTick(); - var success = WaitForConditionOrTimeOutWithTimeTravel(ValidateBitSetValues); - Assert.True(success, $"Timed out waiting for Authoritative Bitset state to equal NonAuthoritative replicated Bitset state!"); - success = WaitForConditionOrTimeOutWithTimeTravel(() => RotationsMatch()); - Assert.True(success, $"[Timed-Out] Authoritative rotation {m_AuthoritativeTransform.transform.rotation.eulerAngles} != Non-Authoritative rotation {m_NonAuthoritativeTransform.transform.rotation.eulerAngles}"); - } - - /// - /// This validates that you can perform multiple explicit calls - /// within the same fractional tick period without the loss of the states applied. - /// - [Test] - public void TestMultipleExplicitSetStates([Values] Interpolation interpolation) - { - var interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritativeTransform.Interpolate = interpolate; - var updatedPosition = GetRandomVector3(-5.0f, 5.0f); - m_AuthoritativeTransform.SetState(updatedPosition, null, null, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - updatedPosition += GetRandomVector3(-5.0f, 5.0f); - m_AuthoritativeTransform.SetState(updatedPosition, null, null, !interpolate); - TimeTravelAdvanceTick(); - - var success = WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatch()); - Assert.True(success, $"[Timed-Out] Authoritative position {m_AuthoritativeTransform.transform.position} != Non-Authoritative position {m_NonAuthoritativeTransform.transform.position}"); - Assert.True(Approximately(updatedPosition, m_NonAuthoritativeTransform.transform.position), $"NonAuthority position {m_NonAuthoritativeTransform.transform.position} does not equal the calculated position {updatedPosition}!"); - - var updatedRotation = m_AuthoritativeTransform.transform.rotation; - updatedRotation.eulerAngles += GetRandomVector3(-30.0f, 30.0f); - m_AuthoritativeTransform.SetState(null, updatedRotation, null, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - updatedRotation.eulerAngles += GetRandomVector3(-30.0f, 30.0f); - m_AuthoritativeTransform.SetState(null, updatedRotation, null, !interpolate); - TimeTravelAdvanceTick(); - - success = WaitForConditionOrTimeOutWithTimeTravel(() => RotationsMatch()); - Assert.True(success, $"[Timed-Out] Authoritative rotation {m_AuthoritativeTransform.transform.rotation.eulerAngles} != Non-Authoritative rotation {m_NonAuthoritativeTransform.transform.rotation.eulerAngles}"); - Assert.True(Approximately(updatedRotation.eulerAngles, m_NonAuthoritativeTransform.transform.rotation.eulerAngles), $"NonAuthority rotation {m_NonAuthoritativeTransform.transform.rotation.eulerAngles} does not equal the calculated rotation {updatedRotation.eulerAngles}!"); - - var updatedScale = m_AuthoritativeTransform.transform.localScale; - updatedScale += GetRandomVector3(-2.0f, 2.0f); - m_AuthoritativeTransform.SetState(null, null, updatedScale, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - updatedScale += GetRandomVector3(-2.0f, 2.0f); - m_AuthoritativeTransform.SetState(null, null, updatedScale, !interpolate); - TimeTravelAdvanceTick(); - - success = WaitForConditionOrTimeOutWithTimeTravel(() => ScaleValuesMatch()); - Assert.True(success, $"[Timed-Out] Authoritative rotation {m_AuthoritativeTransform.transform.localScale} != Non-Authoritative rotation {m_NonAuthoritativeTransform.transform.localScale}"); - Assert.True(Approximately(updatedScale, m_NonAuthoritativeTransform.transform.localScale), $"NonAuthority scale {m_NonAuthoritativeTransform.transform.localScale} does not equal the calculated scale {updatedScale}!"); - - // Now test explicitly setting all axis of transform multiple times during a fractional tick period - updatedPosition += GetRandomVector3(-5.0f, 5.0f); - updatedRotation.eulerAngles += GetRandomVector3(-30.0f, 30.0f); - updatedScale += GetRandomVector3(-2.0f, 2.0f); - m_AuthoritativeTransform.SetState(updatedPosition, updatedRotation, updatedScale, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - updatedPosition += GetRandomVector3(-5.0f, 5.0f); - updatedRotation.eulerAngles += GetRandomVector3(-30.0f, 30.0f); - updatedScale += GetRandomVector3(-2.0f, 2.0f); - m_AuthoritativeTransform.SetState(updatedPosition, updatedRotation, updatedScale, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - updatedPosition += GetRandomVector3(-5.0f, 5.0f); - updatedRotation.eulerAngles += GetRandomVector3(-30.0f, 30.0f); - updatedScale += GetRandomVector3(-2.0f, 2.0f); - m_AuthoritativeTransform.SetState(updatedPosition, updatedRotation, updatedScale, !interpolate); - // Advance to next frame - TimeTravel(0.001f, 1); - - TimeTravelAdvanceTick(); - - success = WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatch() && RotationsMatch() && ScaleValuesMatch()); - Assert.True(success, $"[Timed-Out] Authoritative transform != Non-Authoritative transform!"); - Assert.True(Approximately(updatedPosition, m_NonAuthoritativeTransform.transform.position), $"NonAuthority position {m_NonAuthoritativeTransform.transform.position} does not equal the calculated position {updatedPosition}!"); - Assert.True(Approximately(updatedRotation.eulerAngles, m_NonAuthoritativeTransform.transform.rotation.eulerAngles), $"NonAuthority rotation {m_NonAuthoritativeTransform.transform.rotation.eulerAngles} does not equal the calculated rotation {updatedRotation.eulerAngles}!"); - Assert.True(Approximately(updatedScale, m_NonAuthoritativeTransform.transform.localScale), $"NonAuthority scale {m_NonAuthoritativeTransform.transform.localScale} does not equal the calculated scale {updatedScale}!"); - } - - /// - /// This test validates the method - /// usage for the non-authoritative side. It will either be the owner or the server making/requesting state changes. - /// This validates that: - /// - The owner authoritative mode can still be controlled by the server (i.e. owner authoritative with server authority override capabilities) - /// - The server authoritative mode can still be directed by the client owner. - /// - /// - /// This also tests that the original server authoritative model with client-owner driven NetworkTransforms is preserved. - /// - [Test] - public void NonAuthorityOwnerSettingStateTest([Values] Interpolation interpolation) - { - var interpolate = interpolation != Interpolation.EnableInterpolate; - m_AuthoritativeTransform.Interpolate = interpolate; - m_NonAuthoritativeTransform.Interpolate = interpolate; - m_NonAuthoritativeTransform.RotAngleThreshold = m_AuthoritativeTransform.RotAngleThreshold = 0.1f; - - // Test one parameter at a time first - var newPosition = new Vector3(125f, 35f, 65f); - var newRotation = Quaternion.Euler(1, 2, 3); - var newScale = new Vector3(2.0f, 2.0f, 2.0f); - m_NonAuthoritativeTransform.SetState(newPosition, null, null, interpolate); - var success = WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatchesValue(newPosition)); - Assert.True(success, $"Timed out waiting for non-authoritative position state request to be applied!"); - Assert.True(Approximately(newPosition, m_AuthoritativeTransform.transform.position), "Authoritative position does not match!"); - Assert.True(Approximately(newPosition, m_NonAuthoritativeTransform.transform.position), "Non-Authoritative position does not match!"); - - m_NonAuthoritativeTransform.SetState(null, newRotation, null, interpolate); - success = WaitForConditionOrTimeOutWithTimeTravel(() => RotationMatchesValue(newRotation.eulerAngles)); - Assert.True(success, $"Timed out waiting for non-authoritative rotation state request to be applied!"); - Assert.True(Approximately(newRotation.eulerAngles, m_AuthoritativeTransform.transform.rotation.eulerAngles), "Authoritative rotation does not match!"); - Assert.True(Approximately(newRotation.eulerAngles, m_NonAuthoritativeTransform.transform.rotation.eulerAngles), "Non-Authoritative rotation does not match!"); - - m_NonAuthoritativeTransform.SetState(null, null, newScale, interpolate); - success = WaitForConditionOrTimeOutWithTimeTravel(() => ScaleMatchesValue(newScale)); - Assert.True(success, $"Timed out waiting for non-authoritative scale state request to be applied!"); - Assert.True(Approximately(newScale, m_AuthoritativeTransform.transform.localScale), "Authoritative scale does not match!"); - Assert.True(Approximately(newScale, m_NonAuthoritativeTransform.transform.localScale), "Non-Authoritative scale does not match!"); - - // Test all parameters at once - newPosition = new Vector3(55f, 95f, -25f); - newRotation = Quaternion.Euler(20, 5, 322); - newScale = new Vector3(0.5f, 0.5f, 0.5f); - - m_NonAuthoritativeTransform.SetState(newPosition, newRotation, newScale, interpolate); - success = WaitForConditionOrTimeOutWithTimeTravel(() => PositionRotationScaleMatches(newPosition, newRotation.eulerAngles, newScale)); - Assert.True(success, $"Timed out waiting for non-authoritative position, rotation, and scale state request to be applied!"); - Assert.True(Approximately(newPosition, m_AuthoritativeTransform.transform.position), "Authoritative position does not match!"); - Assert.True(Approximately(newPosition, m_NonAuthoritativeTransform.transform.position), "Non-Authoritative position does not match!"); - Assert.True(Approximately(newRotation.eulerAngles, m_AuthoritativeTransform.transform.rotation.eulerAngles), "Authoritative rotation does not match!"); - Assert.True(Approximately(newRotation.eulerAngles, m_NonAuthoritativeTransform.transform.rotation.eulerAngles), "Non-Authoritative rotation does not match!"); - Assert.True(Approximately(newScale, m_AuthoritativeTransform.transform.localScale), "Authoritative scale does not match!"); - Assert.True(Approximately(newScale, m_NonAuthoritativeTransform.transform.localScale), "Non-Authoritative scale does not match!"); - } - } -} diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs.meta deleted file mode 100644 index 88f78f4..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7a69eaaf3c4b8464a93520a3514bf5e8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs b/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs deleted file mode 100644 index 31105ef..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs +++ /dev/null @@ -1,818 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost, MotionModels.UseTransform)] - [TestFixture(HostOrServer.DAHost, MotionModels.UseRigidbody)] - [TestFixture(HostOrServer.Host, MotionModels.UseTransform)] - internal class NetworkTransformOwnershipTests : IntegrationTestWithApproximation - { - public enum MotionModels - { - UseRigidbody, - UseTransform - } - protected override int NumberOfClients => 1; - - private GameObject m_ClientNetworkTransformPrefab; - private GameObject m_NetworkTransformPrefab; - - private MotionModels m_MotionModel; - - public NetworkTransformOwnershipTests(HostOrServer hostOrServer, MotionModels motionModel) : base(hostOrServer) - { - m_MotionModel = motionModel; - } - - protected override void OnServerAndClientsCreated() - { - VerifyObjectIsSpawnedOnClient.ResetObjectTable(); - m_ClientNetworkTransformPrefab = CreateNetworkObjectPrefab("OwnerAuthorityTest"); - var clientNetworkTransform = m_ClientNetworkTransformPrefab.AddComponent(); - clientNetworkTransform.Interpolate = false; - clientNetworkTransform.UseHalfFloatPrecision = false; - var rigidBody = m_ClientNetworkTransformPrefab.AddComponent(); - rigidBody.useGravity = false; - rigidBody.interpolation = RigidbodyInterpolation.None; - rigidBody.maxLinearVelocity = 0; - // NOTE: We don't use a sphere collider for this integration test because by the time we can - // assure they don't collide and skew the results the NetworkObjects are already synchronized - // with skewed results - var networkRigidbody = m_ClientNetworkTransformPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = m_MotionModel == MotionModels.UseRigidbody; - m_ClientNetworkTransformPrefab.AddComponent(); - - m_NetworkTransformPrefab = CreateNetworkObjectPrefab("ServerAuthorityTest"); - var networkTransform = m_NetworkTransformPrefab.AddComponent(); - rigidBody = m_NetworkTransformPrefab.AddComponent(); - rigidBody.useGravity = false; - rigidBody.interpolation = RigidbodyInterpolation.None; - rigidBody.maxLinearVelocity = 0; - // NOTE: We don't use a sphere collider for this integration test because by the time we can - // assure they don't collide and skew the results the NetworkObjects are already synchronized - // with skewed results - networkRigidbody = m_NetworkTransformPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = m_MotionModel == MotionModels.UseRigidbody; - m_NetworkTransformPrefab.AddComponent(); - networkTransform.Interpolate = false; - networkTransform.UseHalfFloatPrecision = false; - - base.OnServerAndClientsCreated(); - } - - /// - /// Clients created during a test need to have their prefabs list updated to - /// match the server's prefab list. - /// - protected override void OnNewClientCreated(NetworkManager networkManager) - { - foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) - { - networkManager.NetworkConfig.Prefabs.Add(networkPrefab); - } - - base.OnNewClientCreated(networkManager); - } - - private bool ClientIsOwner() - { - var clientId = m_ClientNetworkManagers[0].LocalClientId; - if (!VerifyObjectIsSpawnedOnClient.GetClientsThatSpawnedThisPrefab().Contains(clientId)) - { - return false; - } - if (VerifyObjectIsSpawnedOnClient.GetClientInstance(clientId).OwnerClientId != clientId) - { - return false; - } - return true; - } - - /// - /// This test verifies a late joining client cannot change the transform when: - /// - A NetworkObject is spawned with a host and one or more connected clients - /// - The NetworkTransform is owner authoritative and spawned with the host as the owner - /// - The host does not change the transform values - /// - One of the already connected clients gains ownership of the spawned NetworkObject - /// - The new client owner does not change the transform values - /// - A new late joining client connects and is synchronized - /// - The newly connected late joining client tries to change the transform of the NetworkObject - /// it does not own - /// - [UnityTest] - public IEnumerator LateJoinedNonOwnerClientCannotChangeTransform() - { - // Spawn the m_ClientNetworkTransformPrefab with the host starting as the owner - var hostInstance = SpawnObject(m_ClientNetworkTransformPrefab, m_ServerNetworkManager); - - // Wait for the client to spawn it - yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientsThatSpawnedThisPrefab().Contains(m_ClientNetworkManagers[0].LocalClientId)); - - // Change the ownership to the connectd client - hostInstance.GetComponent().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId); - - // Wait until the client gains ownership - yield return WaitForConditionOrTimeOut(ClientIsOwner); - AssertOnTimeout($"Timed out waiting for the {nameof(ClientIsOwner)} condition to be met!"); - - // Spawn a new client - yield return CreateAndStartNewClient(); - - yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.NetworkManagerRelativeSpawnedObjects.ContainsKey(m_ClientNetworkManagers[1].LocalClientId)); - AssertOnTimeout($"Timed out waiting for late joing client VerifyObjectIsSpawnedOnClient entry to be created!"); - - // Get the instance of the object relative to the newly joined client - var newClientObjectInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ClientNetworkManagers[1].LocalClientId); - - // Attempt to change the transform values - var currentPosition = newClientObjectInstance.transform.position; - newClientObjectInstance.transform.position = GetRandomVector3(0.5f, 10.0f); - var rotation = newClientObjectInstance.transform.rotation; - var currentRotation = rotation.eulerAngles; - rotation.eulerAngles = GetRandomVector3(1.0f, 180.0f); - var currentScale = newClientObjectInstance.transform.localScale; - newClientObjectInstance.transform.localScale = GetRandomVector3(0.25f, 4.0f); - - // Wait one frame so the NetworkTransform can apply the owner's last state received on the late joining client side - // (i.e. prevent the non-owner from changing the transform) - if (m_MotionModel == MotionModels.UseRigidbody) - { - // Allow fixed update to run twice for values to propogate to Unity transform - yield return new WaitForFixedUpdate(); - yield return new WaitForFixedUpdate(); - } - else - { - yield return null; - } - - // Get the owner instance - var ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ClientNetworkManagers[0].LocalClientId); - - // Verify that the non-owner instance transform values are the same before they were changed last frame - Assert.True(Approximately(currentPosition, newClientObjectInstance.transform.position), $"Non-owner instance was able to change the position!"); - Assert.True(Approximately(currentRotation, newClientObjectInstance.transform.rotation.eulerAngles), $"Non-owner instance was able to change the rotation!"); - Assert.True(Approximately(currentScale, newClientObjectInstance.transform.localScale), $"Non-owner instance was able to change the scale!"); - - // Verify that the non-owner instance transform is still the same as the owner instance transform - Assert.True(Approximately(ownerInstance.transform.position, newClientObjectInstance.transform.position), "Non-owner and owner instance position values are not the same!"); - Assert.True(Approximately(ownerInstance.transform.rotation.eulerAngles, newClientObjectInstance.transform.rotation.eulerAngles), "Non-owner and owner instance rotation values are not the same!"); - Assert.True(Approximately(ownerInstance.transform.localScale, newClientObjectInstance.transform.localScale), "Non-owner and owner instance scale values are not the same!"); - } - - public enum StartingOwnership - { - HostStartsAsOwner, - ClientStartsAsOwner, - } - - private bool ClientAndServerSpawnedInstance() - { - return VerifyObjectIsSpawnedOnClient.NetworkManagerRelativeSpawnedObjects.ContainsKey(m_ServerNetworkManager.LocalClientId) && VerifyObjectIsSpawnedOnClient.NetworkManagerRelativeSpawnedObjects.ContainsKey(m_ClientNetworkManagers[0].LocalClientId); - } - - private bool m_UseAdjustedVariance; - private const float k_AdjustedVariance = 0.025f; - - protected override float GetDeltaVarianceThreshold() - { - if (m_UseAdjustedVariance) - { - return k_AdjustedVariance; - } - return base.GetDeltaVarianceThreshold(); - } - - /// - /// This verifies that when authority is owner authoritative the owner's - /// Rigidbody is kinematic and the non-owner's is not. - /// This also verifies that we can switch between owners and that only the - /// owner can update the transform while non-owners cannot. - /// - /// determines who starts as the owner (true): host | (false): client - [UnityTest] - public IEnumerator OwnerAuthoritativeTest([Values] StartingOwnership startingOwnership) - { - // Get the current ownership layout - var networkManagerOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - var networkManagerNonOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - - // Spawn the m_ClientNetworkTransformPrefab and wait for the client-side to spawn the object - var serverSideInstance = SpawnObject(m_ClientNetworkTransformPrefab, networkManagerOwner); - yield return WaitForConditionOrTimeOut(ClientAndServerSpawnedInstance); - AssertOnTimeout($"Timed out waiting for all object instances to be spawned!"); - - // Get owner relative instances - var ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerOwner.LocalClientId); - var nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId); - Assert.NotNull(ownerInstance); - Assert.NotNull(nonOwnerInstance); - Assert.True(networkManagerOwner.LocalClientId != networkManagerNonOwner.LocalClientId); - Assert.True(nonOwnerInstance.OwnerClientId != networkManagerNonOwner.LocalClientId); - Assert.True(nonOwnerInstance.NetworkManager.LocalClientId == networkManagerNonOwner.LocalClientId); - - Vector3 GetNonOwnerPosition() - { - if (m_MotionModel == MotionModels.UseRigidbody) - { - return nonOwnerInstance.GetComponent().position; - } - else - { - return nonOwnerInstance.transform.position; - } - } - - Quaternion GetNonOwnerRotation() - { - if (m_MotionModel == MotionModels.UseRigidbody) - { - return nonOwnerInstance.GetComponent().rotation; - } - else - { - return nonOwnerInstance.transform.rotation; - } - } - - void LogNonOwnerRigidBody(int stage) - { - if (m_MotionModel == MotionModels.UseRigidbody && m_EnableVerboseDebug) - { - var rigidbody = nonOwnerInstance.GetComponent(); - Debug.Log($"[{stage}][Rigidbody-NonOwner][Owner:{nonOwnerInstance.OwnerClientId} [Client-{nonOwnerInstance.NetworkManager.LocalClientId}][Gravity: {rigidbody.useGravity}][Kinematic: {rigidbody.isKinematic}][RB-Pos: {rigidbody.position}][RB-Rotation: {rigidbody.rotation}]"); - } - } - - void LogOwnerRigidBody(int stage) - { - if (m_MotionModel == MotionModels.UseRigidbody && m_EnableVerboseDebug) - { - var rigidbody = ownerInstance.GetComponent(); - Debug.Log($"[{stage}][Rigidbody-Owner][Owner:{ownerInstance.OwnerClientId} [Client-{ownerInstance.NetworkManager.LocalClientId}][Gravity: {rigidbody.useGravity}][Kinematic: {rigidbody.isKinematic}][RB-Pos: {rigidbody.position}][RB-Rotation: {rigidbody.rotation}]"); - } - } - - // Make sure the owner is not kinematic and the non-owner(s) are kinematic - Assert.True(nonOwnerInstance.GetComponent().isKinematic, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!"); - Assert.False(ownerInstance.GetComponent().isKinematic, $"{networkManagerOwner.name}'s object instance {ownerInstance.name} is kinematic when it should not be!"); - if (m_MotionModel == MotionModels.UseRigidbody) - { - nonOwnerInstance.GetComponent().LogStateUpdate = m_EnableVerboseDebug; - } - // Owner changes transform values - var valueSetByOwner = Vector3.one * 2; - var rotation = new Quaternion - { - eulerAngles = valueSetByOwner - }; - if (m_MotionModel == MotionModels.UseRigidbody) - { - var ownerRigidbody = ownerInstance.GetComponent(); - ownerRigidbody.Move(valueSetByOwner, rotation); - ownerRigidbody.linearVelocity = Vector3.zero; - yield return s_DefaultWaitForTick; - ownerInstance.transform.localScale = valueSetByOwner; - } - else - { - ownerInstance.transform.position = valueSetByOwner; - ownerInstance.transform.rotation = rotation; - ownerInstance.transform.localScale = valueSetByOwner; - } - - var transformToTest = nonOwnerInstance.transform; - LogNonOwnerRigidBody(1); - yield return WaitForConditionOrTimeOut(() => Approximately(transformToTest.position, valueSetByOwner) && Approximately(transformToTest.localScale, valueSetByOwner) && Approximately(transformToTest.rotation, rotation)); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change its transform!\n" + - $"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" + - $"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" + - $"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}"); - - // Verify non-owners cannot change transform values - nonOwnerInstance.transform.position = Vector3.zero; - yield return s_DefaultWaitForTick; - if (m_MotionModel == MotionModels.UseRigidbody) - { - yield return new WaitForFixedUpdate(); - } - - LogNonOwnerRigidBody(2); - Assert.True(Approximately(GetNonOwnerPosition(), valueSetByOwner), $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {valueSetByOwner} Is Currently:{GetNonOwnerPosition()}"); - - // Change ownership and wait for the non-owner to reflect the change - VerifyObjectIsSpawnedOnClient.ResetObjectTable(); - if (m_DistributedAuthority) - { - ownerInstance.NetworkObject.ChangeOwnership(networkManagerNonOwner.LocalClientId); - } - else - { - m_ServerNetworkManager.SpawnManager.ChangeOwnership(serverSideInstance.GetComponent(), networkManagerNonOwner.LocalClientId, true); - } - LogNonOwnerRigidBody(3); - yield return WaitForConditionOrTimeOut(() => nonOwnerInstance.GetComponent().OwnerClientId == networkManagerNonOwner.LocalClientId); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change ownership!"); - - LogNonOwnerRigidBody(4); - // Re-assign the ownership references and wait for the non-owner instance to be notified of ownership change - networkManagerOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - networkManagerNonOwner = startingOwnership == StartingOwnership.HostStartsAsOwner ? m_ServerNetworkManager : m_ClientNetworkManagers[0]; - ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerOwner.LocalClientId); - Assert.NotNull(ownerInstance); - yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId) != null); - nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(networkManagerNonOwner.LocalClientId); - Assert.NotNull(nonOwnerInstance); - - // Make sure the owner is not kinematic and the non-owner(s) are kinematic - Assert.False(ownerInstance.GetComponent().isKinematic, $"{networkManagerOwner.name}'s object instance {ownerInstance.name} is kinematic when it should not be!"); - Assert.True(nonOwnerInstance.GetComponent().isKinematic, $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!"); - transformToTest = nonOwnerInstance.transform; - Assert.True(networkManagerOwner.LocalClientId != networkManagerNonOwner.LocalClientId); - Assert.True(nonOwnerInstance.OwnerClientId != networkManagerNonOwner.LocalClientId); - Assert.True(nonOwnerInstance.NetworkManager.LocalClientId == networkManagerNonOwner.LocalClientId); - - yield return WaitForConditionOrTimeOut(() => Approximately(transformToTest.position, valueSetByOwner) && Approximately(transformToTest.localScale, valueSetByOwner) && Approximately(transformToTest.rotation, rotation)); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change its transform!\n" + - $"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" + - $"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" + - $"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}"); - - LogNonOwnerRigidBody(5); - // Have the new owner change transform values and wait for those values to be applied on the non-owner side. - valueSetByOwner = Vector3.one * 10; - ownerInstance.transform.localScale = valueSetByOwner; - rotation.eulerAngles = valueSetByOwner; - LogOwnerRigidBody(1); - if (m_MotionModel == MotionModels.UseRigidbody) - { - m_UseAdjustedVariance = true; - var ownerRigidbody = ownerInstance.GetComponent(); - ownerRigidbody.Move(valueSetByOwner, rotation); - LogOwnerRigidBody(2); - ownerInstance.GetComponent().LogMotion = m_EnableVerboseDebug; - nonOwnerInstance.GetComponent().LogMotion = m_EnableVerboseDebug; - ownerRigidbody.linearVelocity = Vector3.zero; - } - else - { - m_UseAdjustedVariance = false; - ownerInstance.transform.position = valueSetByOwner; - ownerInstance.transform.rotation = rotation; - } - - LogOwnerRigidBody(3); - LogNonOwnerRigidBody(6); - yield return WaitForConditionOrTimeOut(() => Approximately(GetNonOwnerPosition(), valueSetByOwner) && Approximately(transformToTest.localScale, valueSetByOwner) && Approximately(GetNonOwnerRotation(), rotation)); - if (s_GlobalTimeoutHelper.TimedOut) - { - LogOwnerRigidBody(4); - LogNonOwnerRigidBody(7); - } - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} to change its transform!\n" + - $"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" + - $"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" + - $"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}"); - - // The last check is to verify non-owners cannot change transform values after ownership has changed - nonOwnerInstance.transform.position = Vector3.zero; - yield return s_DefaultWaitForTick; - if (m_MotionModel == MotionModels.UseRigidbody) - { - yield return new WaitForFixedUpdate(); - } - Assert.True(Approximately(GetNonOwnerPosition(), valueSetByOwner), $"{networkManagerNonOwner.name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {valueSetByOwner} Is Currently:{GetNonOwnerPosition()}"); - } - - /// - /// This verifies that when authority is server authoritative the - /// client's Rigidbody is kinematic and the server is not. - /// This also verifies only the server can apply updates to the - /// transform while the clients cannot. - /// - [UnityTest] - public IEnumerator ServerAuthoritativeTest() - { - // Spawn the m_NetworkTransformPrefab and wait for the client-side to spawn the object - var serverSideInstance = SpawnObject(m_NetworkTransformPrefab, m_ServerNetworkManager); - yield return WaitForConditionOrTimeOut(() => VerifyObjectIsSpawnedOnClient.GetClientsThatSpawnedThisPrefab().Contains(m_ClientNetworkManagers[0].LocalClientId)); - - var ownerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ServerNetworkManager.LocalClientId); - var nonOwnerInstance = VerifyObjectIsSpawnedOnClient.GetClientInstance(m_ClientNetworkManagers[0].LocalClientId); - - // Make sure the owner is not kinematic and the non-owner(s) are kinematic - Assert.False(ownerInstance.GetComponent().isKinematic, $"{m_ServerNetworkManager.name}'s object instance {ownerInstance.name} is kinematic when it should not be!"); - Assert.True(nonOwnerInstance.GetComponent().isKinematic, $"{m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} is not kinematic when it should be!"); - - // Server changes transform values - var valueSetByOwner = Vector3.one * 2; - ownerInstance.transform.position = valueSetByOwner; - ownerInstance.transform.localScale = valueSetByOwner; - var rotation = new Quaternion - { - eulerAngles = valueSetByOwner - }; - ownerInstance.transform.rotation = rotation; - - // Allow scale to update first when using rigid body motion - if (m_MotionModel == MotionModels.UseRigidbody) - { - yield return new WaitForFixedUpdate(); - } - var transformToTest = nonOwnerInstance.transform; - yield return WaitForConditionOrTimeOut(() => transformToTest.position == valueSetByOwner && transformToTest.localScale == valueSetByOwner && transformToTest.rotation == rotation); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for {m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} to change its transform!\n" + - $"Expected Position: {valueSetByOwner} | Current Position: {transformToTest.position}\n" + - $"Expected Rotation: {valueSetByOwner} | Current Rotation: {transformToTest.rotation.eulerAngles}\n" + - $"Expected Scale: {valueSetByOwner} | Current Scale: {transformToTest.localScale}"); - - // The last check is to verify clients cannot change transform values - nonOwnerInstance.transform.position = Vector3.zero; - yield return s_DefaultWaitForTick; - // Allow scale to update first when using rigid body motion - if (m_MotionModel == MotionModels.UseRigidbody) - { - yield return new WaitForFixedUpdate(); - } - Assert.True(nonOwnerInstance.transform.position == valueSetByOwner, $"{m_ClientNetworkManagers[0].name}'s object instance {nonOwnerInstance.name} was allowed to change its position! Expected: {Vector3.one} Is Currently:{nonOwnerInstance.transform.position}"); - } - - /// - /// NetworkTransformOwnershipTests helper behaviour - /// - internal class VerifyObjectIsSpawnedOnClient : NetworkBehaviour - { - public static Dictionary NetworkManagerRelativeSpawnedObjects = new Dictionary(); - - public static void ResetObjectTable() - { - NetworkManagerRelativeSpawnedObjects.Clear(); - } - - public override void OnGainedOwnership() - { - if (!NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId)) - { - NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this); - } - base.OnGainedOwnership(); - } - - public override void OnLostOwnership() - { - if (!NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId)) - { - NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this); - } - base.OnLostOwnership(); - } - - public static List GetClientsThatSpawnedThisPrefab() - { - return NetworkManagerRelativeSpawnedObjects.Keys.ToList(); - } - - public static VerifyObjectIsSpawnedOnClient GetClientInstance(ulong clientId) - { - if (NetworkManagerRelativeSpawnedObjects.ContainsKey(clientId)) - { - return NetworkManagerRelativeSpawnedObjects[clientId]; - } - return null; - } - - public override void OnNetworkSpawn() - { - if (!NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId)) - { - NetworkManagerRelativeSpawnedObjects.Add(NetworkManager.LocalClientId, this); - } - base.OnNetworkSpawn(); - } - - public override void OnNetworkDespawn() - { - if (NetworkManagerRelativeSpawnedObjects.ContainsKey(NetworkManager.LocalClientId)) - { - NetworkManagerRelativeSpawnedObjects.Remove(NetworkManager.LocalClientId); - } - base.OnNetworkDespawn(); - } - } - - /// - /// Until we can better locate the ClientNetworkTransform - /// This will have to be used to verify the ownership authority - /// - [DisallowMultipleComponent] - internal class TestClientNetworkTransform : NetworkTransform - { - //public override void OnNetworkSpawn() - //{ - // base.OnNetworkSpawn(); - // CanCommitToTransform = IsOwner; - //} - - //protected override void Update() - //{ - // CanCommitToTransform = IsOwner; - // base.Update(); - // if (NetworkManager.Singleton != null && (NetworkManager.Singleton.IsConnectedClient || NetworkManager.Singleton.IsListening)) - // { - // if (CanCommitToTransform) - // { - // TryCommitTransformToServer(transform, NetworkManager.LocalTime.Time); - // } - // } - //} - - protected override bool OnIsServerAuthoritative() - { - return false; - } - } - } - - [TestFixture(HostOrServer.DAHost, NetworkTransform.AuthorityModes.Owner)] // Validate the NetworkTransform owner authoritative mode fix using distributed authority - [TestFixture(HostOrServer.Host, NetworkTransform.AuthorityModes.Server)] // Validate we have not impacted NetworkTransform server authoritative mode - [TestFixture(HostOrServer.Host, NetworkTransform.AuthorityModes.Owner)] // Validate the NetworkTransform owner authoritative mode fix using client-server - internal class NestedNetworkTransformTests : IntegrationTestWithApproximation - { - private const int k_NestedChildren = 5; - protected override int NumberOfClients => 2; - - private GameObject m_SpawnObject; - - private NetworkTransform.AuthorityModes m_AuthorityMode; - - private StringBuilder m_ErrorLog = new StringBuilder(); - - private List m_NetworkManagers = new List(); - private List m_SpawnedObjects = new List(); - - public NestedNetworkTransformTests(HostOrServer hostOrServer, NetworkTransform.AuthorityModes authorityMode) : base(hostOrServer) - { - m_AuthorityMode = authorityMode; - } - - /// - /// Creates a player prefab with several nested NetworkTransforms - /// - protected override void OnCreatePlayerPrefab() - { - var networkTransform = m_PlayerPrefab.AddComponent(); - networkTransform.AuthorityMode = m_AuthorityMode; - var parent = m_PlayerPrefab; - // Add several nested NetworkTransforms - for (int i = 0; i < k_NestedChildren; i++) - { - var nestedChild = new GameObject(); - nestedChild.transform.parent = parent.transform; - var nestedNetworkTransform = nestedChild.AddComponent(); - nestedNetworkTransform.AuthorityMode = m_AuthorityMode; - nestedNetworkTransform.InLocalSpace = true; - parent = nestedChild; - } - base.OnCreatePlayerPrefab(); - } - - private void RandomizeObjectTransformPositions(GameObject gameObject) - { - var networkObject = gameObject.GetComponent(); - Assert.True(networkObject.ChildNetworkBehaviours.Count > 0); - - foreach (var networkTransform in networkObject.NetworkTransforms) - { - networkTransform.gameObject.transform.position = GetRandomVector3(-15.0f, 15.0f); - } - } - - /// - /// Randomizes each player's position when validating distributed authority - /// - /// - private GameObject FetchLocalPlayerPrefabToSpawn() - { - RandomizeObjectTransformPositions(m_PlayerPrefab); - return m_PlayerPrefab; - } - - /// - /// Randomizes the player position when validating client-server - /// - /// - /// - private void ConnectionApprovalHandler(NetworkManager.ConnectionApprovalRequest connectionApprovalRequest, NetworkManager.ConnectionApprovalResponse connectionApprovalResponse) - { - connectionApprovalResponse.Approved = true; - connectionApprovalResponse.CreatePlayerObject = true; - RandomizeObjectTransformPositions(m_PlayerPrefab); - connectionApprovalResponse.Position = GetRandomVector3(-15.0f, 15.0f); - } - - protected override void OnServerAndClientsCreated() - { - // Create a prefab to spawn with each NetworkManager as the owner - m_SpawnObject = CreateNetworkObjectPrefab("SpawnObj"); - var networkTransform = m_SpawnObject.AddComponent(); - networkTransform.AuthorityMode = m_AuthorityMode; - var parent = m_SpawnObject; - // Add several nested NetworkTransforms - for (int i = 0; i < k_NestedChildren; i++) - { - var nestedChild = new GameObject(); - nestedChild.transform.parent = parent.transform; - var nestedNetworkTransform = nestedChild.AddComponent(); - nestedNetworkTransform.AuthorityMode = m_AuthorityMode; - nestedNetworkTransform.InLocalSpace = true; - parent = nestedChild; - } - - if (m_DistributedAuthority) - { - if (!UseCMBService()) - { - m_ServerNetworkManager.OnFetchLocalPlayerPrefabToSpawn = FetchLocalPlayerPrefabToSpawn; - } - - foreach (var client in m_ClientNetworkManagers) - { - client.OnFetchLocalPlayerPrefabToSpawn = FetchLocalPlayerPrefabToSpawn; - } - } - else - { - m_ServerNetworkManager.NetworkConfig.ConnectionApproval = true; - m_ServerNetworkManager.ConnectionApprovalCallback += ConnectionApprovalHandler; - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.ConnectionApproval = true; - } - } - - base.OnServerAndClientsCreated(); - } - - /// - /// Validates the transform positions of two NetworkObject instances - /// - /// the local instance (source of truth) - /// the remote instance - /// - private bool ValidateTransforms(NetworkObject current, NetworkObject testing) - { - if (current.ChildNetworkBehaviours.Count == 0 || testing.ChildNetworkBehaviours.Count == 0) - { - return false; - } - - for (int i = 0; i < current.NetworkTransforms.Count - 1; i++) - { - var transformA = current.NetworkTransforms[i].transform; - var transformB = testing.NetworkTransforms[i].transform; - if (!Approximately(transformA.position, transformB.position)) - { - m_ErrorLog.AppendLine($"TransformA Position {transformA.position} != TransformB Position {transformB.position}"); - return false; - } - if (!Approximately(transformA.localPosition, transformB.localPosition)) - { - m_ErrorLog.AppendLine($"TransformA Local Position {transformA.position} != TransformB Local Position {transformB.position}"); - return false; - } - if (transformA.parent != null) - { - if (current.NetworkTransforms[i].InLocalSpace != testing.NetworkTransforms[i].InLocalSpace) - { - m_ErrorLog.AppendLine($"NetworkTransform-{current.OwnerClientId}-{current.NetworkTransforms[i].NetworkBehaviourId} InLocalSpace ({current.NetworkTransforms[i].InLocalSpace}) is different from the remote instance version on Client-{testing.NetworkManager.LocalClientId}!"); - return false; - } - } - } - return true; - } - - /// - /// Validates all player instances spawned with the correct positions including all nested NetworkTransforms - /// When running in server authority mode we are validating this fix did not impact that. - /// - private bool AllClientInstancesSynchronized() - { - m_ErrorLog.Clear(); - - foreach (var current in m_NetworkManagers) - { - var currentPlayer = current.LocalClient.PlayerObject; - var currentNetworkObjectId = currentPlayer.NetworkObjectId; - foreach (var testing in m_NetworkManagers) - { - if (currentPlayer == testing.LocalClient.PlayerObject) - { - continue; - } - - if (!testing.SpawnManager.SpawnedObjects.ContainsKey(currentNetworkObjectId)) - { - m_ErrorLog.AppendLine($"Failed to find Client-{currentPlayer.OwnerClientId}'s player instance on Client-{testing.LocalClientId}!"); - return false; - } - - var remoteInstance = testing.SpawnManager.SpawnedObjects[currentNetworkObjectId]; - if (!ValidateTransforms(currentPlayer, remoteInstance)) - { - m_ErrorLog.AppendLine($"Failed to validate Client-{currentPlayer.OwnerClientId} against its remote instance on Client-{testing.LocalClientId}!"); - return false; - } - } - } - return true; - } - - /// - /// Validates that dynamically spawning works the same. - /// When running in server authority mode we are validating this fix did not impact that. - /// - /// - private bool AllSpawnedObjectsSynchronized() - { - m_ErrorLog.Clear(); - - foreach (var current in m_SpawnedObjects) - { - var currentNetworkObject = current.GetComponent(); - var currentNetworkObjectId = currentNetworkObject.NetworkObjectId; - foreach (var testing in m_NetworkManagers) - { - if (currentNetworkObject.OwnerClientId == testing.LocalClientId) - { - continue; - } - - if (!testing.SpawnManager.SpawnedObjects.ContainsKey(currentNetworkObjectId)) - { - m_ErrorLog.AppendLine($"Failed to find Client-{currentNetworkObject.OwnerClientId}'s player instance on Client-{testing.LocalClientId}!"); - return false; - } - - var remoteInstance = testing.SpawnManager.SpawnedObjects[currentNetworkObjectId]; - if (!ValidateTransforms(currentNetworkObject, remoteInstance)) - { - m_ErrorLog.AppendLine($"Failed to validate Client-{currentNetworkObject.OwnerClientId} against its remote instance on Client-{testing.LocalClientId}!"); - return false; - } - } - } - return true; - } - - /// - /// Validates that spawning player and dynamically spawned prefab instances with nested NetworkTransforms - /// synchronizes properly in both client-server and distributed authority when using owner authoritative mode. - /// - [UnityTest] - public IEnumerator NestedNetworkTransformSpawnPositionTest() - { - if (!m_DistributedAuthority || (m_DistributedAuthority && !UseCMBService())) - { - m_NetworkManagers.Add(m_ServerNetworkManager); - } - m_NetworkManagers.AddRange(m_ClientNetworkManagers); - - yield return WaitForConditionOrTimeOut(AllClientInstancesSynchronized); - AssertOnTimeout($"Failed to synchronize all client instances!\n{m_ErrorLog}"); - - foreach (var networkManager in m_NetworkManagers) - { - // Randomize the position - RandomizeObjectTransformPositions(m_SpawnObject); - - // Create an instance owned by the specified networkmanager - m_SpawnedObjects.Add(SpawnObject(m_SpawnObject, networkManager)); - } - // Randomize the position once more just to assure we are instantiating remote instances - // with a completely different position - RandomizeObjectTransformPositions(m_SpawnObject); - yield return WaitForConditionOrTimeOut(AllSpawnedObjectsSynchronized); - AssertOnTimeout($"Failed to synchronize all spawned NetworkObject instances!\n{m_ErrorLog}"); - m_SpawnedObjects.Clear(); - m_NetworkManagers.Clear(); - } - - protected override IEnumerator OnTearDown() - { - // In case there was a failure, go ahead and clear these lists out for any pending TextFixture passes - m_SpawnedObjects.Clear(); - m_NetworkManagers.Clear(); - return base.OnTearDown(); - } - } -} -#endif diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs.meta deleted file mode 100644 index b3b6e8c..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b2f8cf0e06334cb4f9f7d4ca3c2d19e3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs b/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs deleted file mode 100644 index 480905c..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs +++ /dev/null @@ -1,501 +0,0 @@ -// TODO: Rewrite test to use the tools package. Debug simulator not available in UTP 2.X. -#if !UTP_TRANSPORT_2_0_ABOVE -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Components; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Integration tests for NetworkTransform that will test both - /// server and host operating modes and will test both authoritative - /// models for each operating mode when packet loss and latency is - /// present. - /// - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Full)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Half)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Euler, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Euler, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Half)] - internal class NetworkTransformPacketLossTests : NetworkTransformBase - { - private const int k_Latency = 50; - private const int k_PacketLoss = 2; - - private Vector3 m_RandomPosition; - private Vector3 m_TeleportOffset = new Vector3(-1024f, 0f, 0f); - private bool m_Teleported; - - /// - /// Constructor - /// - /// Determines if we are running as a server or host - /// Determines if we are using server or owner authority - public NetworkTransformPacketLossTests(HostOrServer testWithHost, Authority authority, RotationCompression rotationCompression, Rotation rotation, Precision precision) : - base(testWithHost, authority, rotationCompression, rotation, precision) - { } - - protected override void OnServerAndClientsCreated() - { - base.OnServerAndClientsCreated(); - - var unityTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport; - unityTransport.SetDebugSimulatorParameters(k_Latency, 0, k_PacketLoss); - } - - /// - /// Handles validating all children of the test objects have matching local and global space vaues. - /// - private IEnumerator AllChildrenLocalTransformValuesMatch(bool useSubChild, ChildrenTransformCheckType checkType) - { - // We don't assert on timeout here because we want to log this information during PostAllChildrenLocalTransformValuesMatch - yield return WaitForConditionOrTimeOut(() => AllInstancesKeptLocalTransformValues(useSubChild)); - var success = true; - if (s_GlobalTimeoutHelper.TimedOut) - { - var waitForMs = new WaitForSeconds(0.0025f); - if (m_Precision == Precision.Half) - { - m_CurrentHalfPrecision = 0.2156f; - } - // If we timed out, then wait for a full range of ticks to assure all data has been synchronized before declaring this a failed test. - for (int j = 0; j < m_ServerNetworkManager.NetworkConfig.TickRate; j++) - { - m_InfoMessage.Clear(); - m_InfoMessage.AppendLine($"[{checkType}][{useSubChild}] Timed out waiting for all children to have the correct local space values:\n"); - var instances = useSubChild ? ChildObjectComponent.SubInstances : ChildObjectComponent.Instances; - success = PostAllChildrenLocalTransformValuesMatch(useSubChild); - yield return waitForMs; - } - } - - if (!success) - { - Assert.True(success, m_InfoMessage.ToString()); - } - } - - /// - /// Validates that transform values remain the same when a NetworkTransform is - /// parented under another NetworkTransform under all of the possible axial conditions - /// as well as when the parent has a varying scale. - /// - [UnityTest] - public IEnumerator ParentedNetworkTransformTest([Values] Interpolation interpolation, [Values] bool worldPositionStays, [Values(0.5f, 1.0f, 5.0f)] float scale) - { - ChildObjectComponent.EnableChildLog = m_EnableVerboseDebug; - if (m_EnableVerboseDebug) - { - ChildObjectComponent.TestCount++; - } - // Get the NetworkManager that will have authority in order to spawn with the correct authority - var isServerAuthority = m_Authority == Authority.ServerAuthority; - var authorityNetworkManager = m_ServerNetworkManager; - if (!isServerAuthority) - { - authorityNetworkManager = m_ClientNetworkManagers[0]; - } - - // Spawn a parent and children - ChildObjectComponent.HasSubChild = true; - var serverSideParent = SpawnObject(m_ParentObject.gameObject, authorityNetworkManager).GetComponent(); - var serverSideChild = SpawnObject(m_ChildObject.gameObject, authorityNetworkManager).GetComponent(); - var serverSideSubChild = SpawnObject(m_SubChildObject.gameObject, authorityNetworkManager).GetComponent(); - - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - - // Assure all of the child object instances are spawned before proceeding to parenting - yield return WaitForConditionOrTimeOut(AllChildObjectInstancesAreSpawned); - AssertOnTimeout("Timed out waiting for all child instances to be spawned!"); - - // Get the authority parent and child instances - m_AuthorityParentObject = NetworkTransformTestComponent.AuthorityInstance.NetworkObject; - m_AuthorityChildObject = ChildObjectComponent.AuthorityInstance.NetworkObject; - m_AuthoritySubChildObject = ChildObjectComponent.AuthoritySubInstance.NetworkObject; - - // The child NetworkTransform will use world space when world position stays and - // local space when world position does not stay when parenting. - ChildObjectComponent.AuthorityInstance.InLocalSpace = !worldPositionStays; - ChildObjectComponent.AuthorityInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthorityInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthorityInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - ChildObjectComponent.AuthoritySubInstance.InLocalSpace = !worldPositionStays; - ChildObjectComponent.AuthoritySubInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - // Set whether we are interpolating or not - m_AuthorityParentNetworkTransform = m_AuthorityParentObject.GetComponent(); - m_AuthorityParentNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthorityChildNetworkTransform = m_AuthorityChildObject.GetComponent(); - m_AuthorityChildNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritySubChildNetworkTransform = m_AuthoritySubChildObject.GetComponent(); - m_AuthoritySubChildNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - - // Apply a scale to the parent object to make sure the scale on the child is properly updated on - // non-authority instances. - var halfScale = scale * 0.5f; - m_AuthorityParentObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthorityChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthoritySubChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - - // Allow one tick for authority to update these changes - - yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches); - - AssertOnTimeout("All transform values did not match prior to parenting!"); - - // Parent the child under the parent with the current world position stays setting - Assert.True(serverSideChild.TrySetParent(serverSideParent.transform, worldPositionStays), "[Server-Side Child] Failed to set child's parent!"); - - // Parent the sub-child under the child with the current world position stays setting - Assert.True(serverSideSubChild.TrySetParent(serverSideChild.transform, worldPositionStays), "[Server-Side SubChild] Failed to set sub-child's parent!"); - - // This waits for all child instances to be parented - yield return WaitForConditionOrTimeOut(AllChildObjectInstancesHaveChild); - AssertOnTimeout("Timed out waiting for all instances to have parented a child!"); - var latencyWait = new WaitForSeconds(k_Latency * 0.003f); - // Wait for at least 3x designated latency period - yield return latencyWait; - - // This validates each child instance has preserved their local space values - yield return AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Connected_Clients); - - // This validates each sub-child instance has preserved their local space values - yield return AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Connected_Clients); - - // Verify that a late joining client will synchronize to the parented NetworkObjects properly - yield return CreateAndStartNewClient(); - - // Assure all of the child object instances are spawned (basically for the newly connected client) - yield return WaitForConditionOrTimeOut(AllChildObjectInstancesAreSpawned); - AssertOnTimeout("Timed out waiting for all child instances to be spawned!"); - - // This waits for all child instances to be parented - yield return WaitForConditionOrTimeOut(AllChildObjectInstancesHaveChild); - AssertOnTimeout("Timed out waiting for all instances to have parented a child!"); - - // Wait for at least 3x designated latency period - yield return latencyWait; - - // This validates each child instance has preserved their local space values - yield return AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Late_Join_Client); - - // This validates each sub-child instance has preserved their local space values - yield return AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Late_Join_Client); - } - - /// - /// This validates that multiple changes can occur within the same tick or over - /// several ticks while still keeping non-authoritative instances synchronized. - /// - /// - /// When testing < 3 axis: Interpolation is disabled and only 3 delta updates are applied per unique test - /// When testing 3 axis: Interpolation is enabled, sometimes an axis is intentionally excluded during a - /// delta update, and it runs through 8 delta updates per unique test. - /// - [UnityTest] - public IEnumerator NetworkTransformMultipleChangesOverTime([Values] TransformSpace testLocalTransform, [Values] Axis axis) - { - yield return s_DefaultWaitForTick; - // Just test for OverrideState.Update (they are already being tested for functionality in normal NetworkTransformTests) - var overideState = OverrideState.Update; - var tickRelativeTime = new WaitForSeconds(1.0f / m_ServerNetworkManager.NetworkConfig.TickRate); - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - bool axisX = axis == Axis.X || axis == Axis.XY || axis == Axis.XZ || axis == Axis.XYZ; - bool axisY = axis == Axis.Y || axis == Axis.XY || axis == Axis.YZ || axis == Axis.XYZ; - bool axisZ = axis == Axis.Z || axis == Axis.XZ || axis == Axis.YZ || axis == Axis.XYZ; - - var axisCount = axisX ? 1 : 0; - axisCount += axisY ? 1 : 0; - axisCount += axisZ ? 1 : 0; - - m_AuthoritativeTransform.StatePushed = false; - // Enable interpolation when all 3 axis are selected to make sure we are synchronizing properly - // when interpolation is enabled. - m_AuthoritativeTransform.Interpolate = axisCount == 3 ? true : false; - - m_CurrentAxis = axis; - - // Authority dictates what is synchronized and what the precision is going to be - // so we only need to set this on the authoritative side. - m_AuthoritativeTransform.UseHalfFloatPrecision = m_Precision == Precision.Half; - m_AuthoritativeTransform.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - m_AuthoritativeTransform.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - m_AuthoritativeTransform.SyncPositionX = axisX; - m_AuthoritativeTransform.SyncPositionY = axisY; - m_AuthoritativeTransform.SyncPositionZ = axisZ; - - if (!m_AuthoritativeTransform.UseQuaternionSynchronization) - { - m_AuthoritativeTransform.SyncRotAngleX = axisX; - m_AuthoritativeTransform.SyncRotAngleY = axisY; - m_AuthoritativeTransform.SyncRotAngleZ = axisZ; - } - else - { - // This is not required for usage (setting the value should not matter when quaternion synchronization is enabled) - // but is required for this test so we don't get a failure on an axis that is marked to not be synchronized when - // validating the authority's values on non-authority instances. - m_AuthoritativeTransform.SyncRotAngleX = true; - m_AuthoritativeTransform.SyncRotAngleY = true; - m_AuthoritativeTransform.SyncRotAngleZ = true; - } - - m_AuthoritativeTransform.SyncScaleX = axisX; - m_AuthoritativeTransform.SyncScaleY = axisY; - m_AuthoritativeTransform.SyncScaleZ = axisZ; - - var positionStart = GetRandomVector3(0.25f, 1.75f); - var rotationStart = GetRandomVector3(1f, 15f); - var scaleStart = GetRandomVector3(0.25f, 2.0f); - var position = positionStart; - var rotation = rotationStart; - var scale = scaleStart; - var success = false; - - - // Wait for the deltas to be pushed - yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed); - - // Just in case we drop the first few state updates - if (s_GlobalTimeoutHelper.TimedOut) - { - // Set the local state to not reflect the authority state's local space settings - // to trigger the state update (it would eventually get there, but this is an integration test) - var state = m_AuthoritativeTransform.LocalAuthoritativeNetworkState; - state.InLocalSpace = !m_AuthoritativeTransform.InLocalSpace; - m_AuthoritativeTransform.LocalAuthoritativeNetworkState = state; - // Wait for the deltas to be pushed - yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed); - } - AssertOnTimeout("State was never pushed!"); - - // Allow the precision settings to propagate first as changing precision - // causes a teleport event to occur - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - yield return s_DefaultWaitForTick; - var iterations = axisCount == 3 ? k_PositionRotationScaleIterations3Axis : k_PositionRotationScaleIterations; - - // Move and rotate within the same tick, validate the non-authoritative instance updates - // to each set of changes. Repeat several times. - for (int i = 0; i < iterations; i++) - { - // Always reset this per delta update pass - m_AxisExcluded = false; - var deltaPositionDelta = GetRandomVector3(-1.5f, 1.5f); - var deltaRotationDelta = GetRandomVector3(-3.5f, 3.5f); - var deltaScaleDelta = GetRandomVector3(-0.5f, 0.5f); - - m_NonAuthoritativeTransform.StateUpdated = false; - m_AuthoritativeTransform.StatePushed = false; - - // With two or more axis, excluding one of them while chaging another will validate that - // full precision updates are maintaining their target state value(s) to interpolate towards - if (axisCount == 3) - { - position += RandomlyExcludeAxis(deltaPositionDelta); - rotation += RandomlyExcludeAxis(deltaRotationDelta); - scale += RandomlyExcludeAxis(deltaScaleDelta); - } - else - { - position += deltaPositionDelta; - rotation += deltaRotationDelta; - scale += deltaScaleDelta; - } - - // Apply delta between ticks - MoveRotateAndScaleAuthority(position, rotation, scale, overideState); - - // Wait for the deltas to be pushed (unlike the original test, we don't wait for state to be updated as that could be dropped here) - yield return WaitForConditionOrTimeOut(() => m_AuthoritativeTransform.StatePushed); - AssertOnTimeout($"[Non-Interpolate {i}] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed})!"); - - // For 3 axis, we will skip validating that the non-authority interpolates to its target point at least once. - // This will validate that non-authoritative updates are maintaining their target state axis values if only 2 - // of the axis are being updated to assure interpolation maintains the targeted axial value per axis. - // For 2 and 1 axis tests we always validate per delta update - if (m_AxisExcluded || axisCount < 3) - { - // Wait for deltas to synchronize on non-authoritative side - yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches); - // Provide additional debug info about what failed (if it fails) - if (s_GlobalTimeoutHelper.TimedOut) - { - Debug.Log("[Synch Issue Start - 1]"); - // If we timed out, then wait for a full range of ticks (plus 1) to assure it sent synchronization data. - for (int j = 0; j < m_ServerNetworkManager.NetworkConfig.TickRate * 2; j++) - { - success = PositionRotationScaleMatches(); - if (success) - { - // If we matched, then something was dropped and recovered when synchronized - break; - } - yield return s_DefaultWaitForTick; - } - - // Only if we still didn't match - if (!success) - { - m_EnableVerboseDebug = true; - success = PositionRotationScaleMatches(); - m_EnableVerboseDebug = false; - Debug.Log("[Synch Issue END - 1]"); - AssertOnTimeout($"[Non-Interpolate {i}] Timed out waiting for non-authority to match authority's position or rotation"); - } - } - } - } - - if (axisCount == 3) - { - // As a final test, wait for deltas to synchronize on non-authoritative side to assure it interpolates to the correct values - yield return WaitForConditionOrTimeOut(PositionRotationScaleMatches); - // Provide additional debug info about what failed (if it fails) - if (s_GlobalTimeoutHelper.TimedOut) - { - Debug.Log("[Synch Issue Start - 2]"); - // If we timed out, then wait for a full range of ticks (plus 1) to assure it sent synchronization data. - for (int j = 0; j < m_ServerNetworkManager.NetworkConfig.TickRate * 2; j++) - { - success = PositionRotationScaleMatches(); - if (success) - { - // If we matched, then something was dropped and recovered when synchronized - break; - } - yield return s_DefaultWaitForTick; - } - - // Only if we still didn't match - if (!success) - { - m_EnableVerboseDebug = true; - PositionRotationScaleMatches(); - m_EnableVerboseDebug = false; - Debug.Log("[Synch Issue END - 2]"); - AssertOnTimeout("Timed out waiting for non-authority to match authority's position or rotation"); - - } - } - - } - } - - /// - /// Tests changing all axial values one at a time with packet loss - /// These tests are performed: - /// - While in local space and world space - /// - While interpolation is enabled and disabled - /// - [UnityTest] - public IEnumerator TestAuthoritativeTransformChangeOneAtATime([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation) - { - // Just test for OverrideState.Update (they are already being tested for functionality in normal NetworkTransformTests) - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - m_AuthoritativeTransform.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - m_AuthoritativeTransform.UseHalfFloatPrecision = m_Precision == Precision.Half; - m_AuthoritativeTransform.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - - // test position - var authPlayerTransform = m_AuthoritativeTransform.transform; - - Assert.AreEqual(Vector3.zero, m_NonAuthoritativeTransform.transform.position, "server side pos should be zero at first"); // sanity check - - m_AuthoritativeTransform.transform.position = GetRandomVector3(2f, 30f); - - yield return WaitForConditionOrTimeOut(() => PositionsMatch()); - AssertOnTimeout($"Timed out waiting for positions to match {m_AuthoritativeTransform.transform.position} | {m_NonAuthoritativeTransform.transform.position}"); - - // test rotation - Assert.AreEqual(Quaternion.identity, m_NonAuthoritativeTransform.transform.rotation, "wrong initial value for rotation"); // sanity check - - m_AuthoritativeTransform.transform.rotation = Quaternion.Euler(GetRandomVector3(5, 60)); // using euler angles instead of quaternions directly to really see issues users might encounter - - // Make sure the values match - yield return WaitForConditionOrTimeOut(() => RotationsMatch()); - AssertOnTimeout($"Timed out waiting for rotations to match"); - - m_AuthoritativeTransform.StatePushed = false; - m_AuthoritativeTransform.transform.localScale = GetRandomVector3(1, 6); - - // Make sure the scale values match - yield return WaitForConditionOrTimeOut(() => ScaleValuesMatch()); - AssertOnTimeout($"Timed out waiting for scale values to match"); - } - - [UnityTest] - public IEnumerator TestSameFrameDeltaStateAndTeleport([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation) - { - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - - // test position - var authPlayerTransform = m_AuthoritativeTransform.transform; - - Assert.AreEqual(Vector3.zero, m_NonAuthoritativeTransform.transform.position, "server side pos should be zero at first"); // sanity check - - m_AuthoritativeTransform.AuthorityPushedTransformState += OnAuthorityPushedTransformState; - m_RandomPosition = GetRandomVector3(2f, 30f); - m_AuthoritativeTransform.transform.position = m_RandomPosition; - m_Teleported = false; - yield return WaitForConditionOrTimeOut(() => m_Teleported); - AssertOnTimeout($"Timed out waiting for random position to be pushed!"); - - yield return WaitForConditionOrTimeOut(() => PositionsMatch()); - AssertOnTimeout($"Timed out waiting for positions to match {m_AuthoritativeTransform.transform.position} | {m_NonAuthoritativeTransform.transform.position}"); - - var authPosition = m_AuthoritativeTransform.GetSpaceRelativePosition(); - var nonAuthPosition = m_NonAuthoritativeTransform.GetSpaceRelativePosition(); - - var finalPosition = m_TeleportOffset + m_RandomPosition; - Assert.True(Approximately(authPosition, finalPosition), $"Authority did not set its position ({authPosition}) to the teleport position ({finalPosition})!"); - Assert.True(Approximately(nonAuthPosition, finalPosition), $"NonAuthority did not set its position ({nonAuthPosition}) to the teleport position ({finalPosition})!"); - } - - /// - /// For the TestSameFrameDeltaStateAndTeleport test, we want to teleport on the same frame that we had a delta state update when - /// using unreliable delta state updates (i.e. we want the unreliable packet to be sent first and then the teleport to be sent on - /// the next tick. Store off both states when invoked - /// - /// - private void OnAuthorityPushedTransformState(ref NetworkTransform.NetworkTransformState networkTransformState) - { - // Match the first position update - if (Approximately(m_RandomPosition, networkTransformState.GetPosition())) - { - // Teleport to the m_RandomPosition plus the - m_AuthoritativeTransform.SetState(m_TeleportOffset + m_RandomPosition, null, null, false); - m_AuthoritativeTransform.AuthorityPushedTransformState -= OnAuthorityPushedTransformState; - m_Teleported = true; - } - } - } -} -#endif diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs.meta deleted file mode 100644 index c363dc6..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformPacketLossTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e0f584e8eb891d5459373e96e54fe821 -timeCreated: 1620872927 \ No newline at end of file diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs b/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs deleted file mode 100644 index 0b47dff..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs +++ /dev/null @@ -1,911 +0,0 @@ -#if !MULTIPLAYER_TOOLS -using NUnit.Framework; -using Unity.Netcode.Components; -using UnityEngine; - - -namespace Unity.Netcode.RuntimeTests -{ - - [TestFixture(TransformSpace.World, Precision.Full, Rotation.Euler)] - [TestFixture(TransformSpace.World, Precision.Half, Rotation.Euler)] - [TestFixture(TransformSpace.Local, Precision.Full, Rotation.Euler)] - [TestFixture(TransformSpace.Local, Precision.Half, Rotation.Euler)] - [TestFixture(TransformSpace.World, Precision.Full, Rotation.Quaternion)] - [TestFixture(TransformSpace.World, Precision.Half, Rotation.Quaternion)] - [TestFixture(TransformSpace.Local, Precision.Full, Rotation.Quaternion)] - [TestFixture(TransformSpace.Local, Precision.Half, Rotation.Quaternion)] - internal class NetworkTransformStateTests - { - public enum SyncAxis - { - SyncPosX, - SyncPosY, - SyncPosZ, - SyncPosXY, - SyncPosXZ, - SyncPosYZ, - SyncPosXYZ, - SyncRotX, - SyncRotY, - SyncRotZ, - SyncRotXY, - SyncRotXZ, - SyncRotYZ, - SyncRotXYZ, - SyncScaleX, - SyncScaleY, - SyncScaleZ, - SyncScaleXY, - SyncScaleXZ, - SyncScaleYZ, - SyncScaleXYZ, - SyncAllX, - SyncAllY, - SyncAllZ, - SyncAllXY, - SyncAllXZ, - SyncAllYZ, - SyncAllXYZ - } - - public enum TransformSpace - { - World, - Local - } - - public enum Rotation - { - Euler, - Quaternion - } - - public enum SynchronizationType - { - Delta, - Teleport - } - - public enum Precision - { - Half, - Full - } - - private TransformSpace m_TransformSpace; - private Precision m_Precision; - private Rotation m_Rotation; - - public NetworkTransformStateTests(TransformSpace transformSpace, Precision precision, Rotation rotation) - { - m_TransformSpace = transformSpace; - m_Precision = precision; - m_Rotation = rotation; - } - - private bool WillAnAxisBeSynchronized(ref NetworkTransform networkTransform) - { - return networkTransform.SyncScaleX || networkTransform.SyncScaleY || networkTransform.SyncScaleZ || - networkTransform.SyncRotAngleX || networkTransform.SyncRotAngleY || networkTransform.SyncRotAngleZ || - networkTransform.SyncPositionX || networkTransform.SyncPositionY || networkTransform.SyncPositionZ; - } - - [Test] - public void NetworkTransformStateFlags() - { - var indexValues = new System.Collections.Generic.List(); - var currentFlag = (uint)0x00000001; - for (int j = 0; j < 18; j++) - { - indexValues.Add(currentFlag); - currentFlag = currentFlag << 1; - } - - // TrackByStateId is unique - indexValues.Add(0x10000000); - - var boolSet = new System.Collections.Generic.List(); - var transformState = new NetworkTransform.NetworkTransformState(); - // Test setting one at a time. - for (int j = 0; j < 19; j++) - { - boolSet = new System.Collections.Generic.List(); - for (int i = 0; i < 19; i++) - { - if (i == j) - { - boolSet.Add(true); - } - else - { - boolSet.Add(false); - } - } - transformState = new NetworkTransform.NetworkTransformState() - { - InLocalSpace = boolSet[0], - HasPositionX = boolSet[1], - HasPositionY = boolSet[2], - HasPositionZ = boolSet[3], - HasRotAngleX = boolSet[4], - HasRotAngleY = boolSet[5], - HasRotAngleZ = boolSet[6], - HasScaleX = boolSet[7], - HasScaleY = boolSet[8], - HasScaleZ = boolSet[9], - IsTeleportingNextFrame = boolSet[10], - UseInterpolation = boolSet[11], - QuaternionSync = boolSet[12], - QuaternionCompression = boolSet[13], - UseHalfFloatPrecision = boolSet[14], - IsSynchronizing = boolSet[15], - UsePositionSlerp = boolSet[16], - IsParented = boolSet[17], - TrackByStateId = boolSet[18], - }; - Assert.True((transformState.BitSet & indexValues[j]) == indexValues[j], $"[FlagTest][Individual] Set flag value {indexValues[j]} at index {j}, but BitSet value did not match!"); - } - - // Test setting all flag values - boolSet = new System.Collections.Generic.List(); - for (int i = 0; i < 19; i++) - { - boolSet.Add(true); - } - - transformState = new NetworkTransform.NetworkTransformState() - { - InLocalSpace = boolSet[0], - HasPositionX = boolSet[1], - HasPositionY = boolSet[2], - HasPositionZ = boolSet[3], - HasRotAngleX = boolSet[4], - HasRotAngleY = boolSet[5], - HasRotAngleZ = boolSet[6], - HasScaleX = boolSet[7], - HasScaleY = boolSet[8], - HasScaleZ = boolSet[9], - IsTeleportingNextFrame = boolSet[10], - UseInterpolation = boolSet[11], - QuaternionSync = boolSet[12], - QuaternionCompression = boolSet[13], - UseHalfFloatPrecision = boolSet[14], - IsSynchronizing = boolSet[15], - UsePositionSlerp = boolSet[16], - IsParented = boolSet[17], - TrackByStateId = boolSet[18], - }; - - for (int j = 0; j < 19; j++) - { - Assert.True((transformState.BitSet & indexValues[j]) == indexValues[j], $"[FlagTest][All] All flag values are set but failed to detect flag value {indexValues[j]}!"); - } - - // Test getting all flag values - transformState = new NetworkTransform.NetworkTransformState(); - for (int i = 0; i < 19; i++) - { - transformState.BitSet |= indexValues[i]; - } - - Assert.True(transformState.InLocalSpace, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.InLocalSpace)}!"); - Assert.True(transformState.HasPositionX, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasPositionX)}!"); - Assert.True(transformState.HasPositionY, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasPositionY)}!"); - Assert.True(transformState.HasPositionZ, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasPositionZ)}!"); - Assert.True(transformState.HasRotAngleX, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasRotAngleX)}!"); - Assert.True(transformState.HasRotAngleY, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasRotAngleY)}!"); - Assert.True(transformState.HasRotAngleZ, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasRotAngleZ)}!"); - Assert.True(transformState.HasScaleX, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasScaleX)}!"); - Assert.True(transformState.HasScaleY, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasScaleY)}!"); - Assert.True(transformState.HasScaleZ, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.HasScaleZ)}!"); - Assert.True(transformState.IsTeleportingNextFrame, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.IsTeleportingNextFrame)}!"); - Assert.True(transformState.UseInterpolation, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.UseInterpolation)}!"); - Assert.True(transformState.QuaternionSync, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.QuaternionSync)}!"); - Assert.True(transformState.QuaternionCompression, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.QuaternionCompression)}!"); - Assert.True(transformState.UseHalfFloatPrecision, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.UseHalfFloatPrecision)}!"); - Assert.True(transformState.IsSynchronizing, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.IsSynchronizing)}!"); - Assert.True(transformState.UsePositionSlerp, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.UsePositionSlerp)}!"); - Assert.True(transformState.IsParented, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.IsParented)}!"); - Assert.True(transformState.TrackByStateId, $"[FlagTest][Get] Failed to detect {nameof(NetworkTransform.NetworkTransformState.TrackByStateId)}!"); - } - - [Test] - public void TestSyncAxes([Values] SynchronizationType synchronizationType, [Values] SyncAxis syncAxis) - - { - bool inLocalSpace = m_TransformSpace == TransformSpace.Local; - bool isTeleporting = synchronizationType == SynchronizationType.Teleport; - bool syncPosX = syncAxis == SyncAxis.SyncPosX || syncAxis == SyncAxis.SyncPosXY || syncAxis == SyncAxis.SyncPosXZ || syncAxis == SyncAxis.SyncPosXYZ || syncAxis == SyncAxis.SyncAllX || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncPosY = syncAxis == SyncAxis.SyncPosY || syncAxis == SyncAxis.SyncPosXY || syncAxis == SyncAxis.SyncPosYZ || syncAxis == SyncAxis.SyncPosXYZ || syncAxis == SyncAxis.SyncAllY || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncPosZ = syncAxis == SyncAxis.SyncPosZ || syncAxis == SyncAxis.SyncPosXZ || syncAxis == SyncAxis.SyncPosYZ || syncAxis == SyncAxis.SyncPosXYZ || syncAxis == SyncAxis.SyncAllZ || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - - bool syncRotX = syncAxis == SyncAxis.SyncRotX || syncAxis == SyncAxis.SyncRotXY || syncAxis == SyncAxis.SyncRotXZ || syncAxis == SyncAxis.SyncRotXYZ || syncAxis == SyncAxis.SyncRotX || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncRotY = syncAxis == SyncAxis.SyncRotY || syncAxis == SyncAxis.SyncRotXY || syncAxis == SyncAxis.SyncRotYZ || syncAxis == SyncAxis.SyncRotXYZ || syncAxis == SyncAxis.SyncRotY || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncRotZ = syncAxis == SyncAxis.SyncRotZ || syncAxis == SyncAxis.SyncRotXZ || syncAxis == SyncAxis.SyncRotYZ || syncAxis == SyncAxis.SyncRotXYZ || syncAxis == SyncAxis.SyncRotZ || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - - bool syncScaX = syncAxis == SyncAxis.SyncScaleX || syncAxis == SyncAxis.SyncScaleXY || syncAxis == SyncAxis.SyncScaleXZ || syncAxis == SyncAxis.SyncScaleXYZ || syncAxis == SyncAxis.SyncAllX || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncScaY = syncAxis == SyncAxis.SyncScaleY || syncAxis == SyncAxis.SyncScaleXY || syncAxis == SyncAxis.SyncScaleYZ || syncAxis == SyncAxis.SyncScaleXYZ || syncAxis == SyncAxis.SyncAllY || syncAxis == SyncAxis.SyncAllXY || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - bool syncScaZ = syncAxis == SyncAxis.SyncScaleZ || syncAxis == SyncAxis.SyncScaleXZ || syncAxis == SyncAxis.SyncScaleYZ || syncAxis == SyncAxis.SyncScaleXYZ || syncAxis == SyncAxis.SyncAllZ || syncAxis == SyncAxis.SyncAllXZ || syncAxis == SyncAxis.SyncAllYZ || syncAxis == SyncAxis.SyncAllXYZ; - - var gameObject = new GameObject($"Test-{nameof(NetworkTransformStateTests)}.{nameof(TestSyncAxes)}"); - var networkObject = gameObject.AddComponent(); - var networkTransform = gameObject.AddComponent(); - - var manager = new GameObject($"Test-{nameof(NetworkManager)}.{nameof(TestSyncAxes)}"); - var networkManager = manager.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig(); - - networkObject.NetworkManagerOwner = networkManager; - - networkTransform.enabled = false; // do not tick `FixedUpdate()` or `Update()` - - var initialPosition = Vector3.zero; - var initialRotAngles = Vector3.zero; - var initialScale = Vector3.one; - networkTransform.UseHalfFloatPrecision = m_Precision == Precision.Half; - networkTransform.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - networkTransform.transform.position = initialPosition; - networkTransform.transform.eulerAngles = initialRotAngles; - networkTransform.transform.localScale = initialScale; - networkTransform.SyncPositionX = syncPosX; - networkTransform.SyncPositionY = syncPosY; - networkTransform.SyncPositionZ = syncPosZ; - networkTransform.SyncRotAngleX = syncRotX; - networkTransform.SyncRotAngleY = syncRotY; - networkTransform.SyncRotAngleZ = syncRotZ; - networkTransform.SyncScaleX = syncScaX; - networkTransform.SyncScaleY = syncScaY; - networkTransform.SyncScaleZ = syncScaZ; - networkTransform.InLocalSpace = inLocalSpace; - - // We want a relatively clean networkTransform state before we try to apply the transform to it - // We only preserve InLocalSpace and IsTeleportingNextFrame properties as they are the only things - // needed when applying a transform to a NetworkTransformState - var networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - NetworkDeltaPosition = new NetworkDeltaPosition(Vector3.zero, 0) - }; - - // Step 1: change properties, expect state to be dirty - { - networkTransform.transform.position = new Vector3(3, 4, 5); - networkTransform.transform.eulerAngles = new Vector3(30, 45, 90); - networkTransform.transform.localScale = new Vector3(1.1f, 0.5f, 2.5f); - - if (syncPosX || syncPosY || syncPosZ || syncRotX || syncRotY || syncRotZ || syncScaX || syncScaY || syncScaZ) - { - Assert.NotNull(networkTransform.NetworkManager, "NetworkManager is NULL!"); - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - var position = networkTransform.transform.position; - var rotAngles = networkTransform.transform.eulerAngles; - var scale = networkTransform.transform.localScale; - - // Step 2: Verify the state changes in a tick are additive - // TODO: This will need to change if we update NetworkTransform to send all of the - // axis deltas that happened over a tick as a collection instead of collapsing them - // as the changes are detected. - { - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - - // SyncPositionX - if (syncPosX) - { - position.x++; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX); - } - - // SyncPositionY - if (syncPosY) - { - position = networkTransform.transform.position; - position.y++; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY); - } - - // SyncPositionZ - if (syncPosZ) - { - position = networkTransform.transform.position; - position.z++; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ); - } - - // SyncRotAngleX - if (syncRotX) - { - rotAngles = networkTransform.transform.eulerAngles; - rotAngles.x++; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX); - } - - // SyncRotAngleY - if (syncRotY) - { - rotAngles = networkTransform.transform.eulerAngles; - rotAngles.y++; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX || !syncRotX); - Assert.IsTrue(networkTransformState.HasRotAngleY); - } - // SyncRotAngleZ - if (syncRotZ) - { - rotAngles = networkTransform.transform.eulerAngles; - rotAngles.z++; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX || !syncRotX); - Assert.IsTrue(networkTransformState.HasRotAngleY || !syncRotY); - Assert.IsTrue(networkTransformState.HasRotAngleZ); - } - - // SyncScaleX - if (syncScaX) - { - scale = networkTransform.transform.localScale; - scale.x++; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX || !syncRotX); - Assert.IsTrue(networkTransformState.HasRotAngleY || !syncRotY); - Assert.IsTrue(networkTransformState.HasRotAngleZ || !syncRotZ); - Assert.IsTrue(networkTransformState.HasScaleX); - } - // SyncScaleY - if (syncScaY) - { - scale = networkTransform.transform.localScale; - scale.y++; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX || !syncRotX); - Assert.IsTrue(networkTransformState.HasRotAngleY || !syncRotY); - Assert.IsTrue(networkTransformState.HasRotAngleZ || !syncRotZ); - Assert.IsTrue(networkTransformState.HasScaleX || !syncScaX); - Assert.IsTrue(networkTransformState.HasScaleY); - } - // SyncScaleZ - if (syncScaZ) - { - scale = networkTransform.transform.localScale; - scale.z++; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsTrue(networkTransformState.HasPositionX || !syncPosX); - Assert.IsTrue(networkTransformState.HasPositionY || !syncPosY); - Assert.IsTrue(networkTransformState.HasPositionZ || !syncPosZ); - Assert.IsTrue(networkTransformState.HasRotAngleX || !syncRotX); - Assert.IsTrue(networkTransformState.HasRotAngleY || !syncRotY); - Assert.IsTrue(networkTransformState.HasRotAngleZ || !syncRotZ); - Assert.IsTrue(networkTransformState.HasScaleX || !syncScaX); - Assert.IsTrue(networkTransformState.HasScaleY || !syncScaY); - Assert.IsTrue(networkTransformState.HasScaleZ); - } - } - - // Step 3: disable a particular sync flag, expect state to be not dirty - // We do this last because it changes which axis will be synchronized. - { - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - - position = networkTransform.transform.position; - rotAngles = networkTransform.transform.eulerAngles; - scale = networkTransform.transform.localScale; - - // SyncPositionX - if (syncPosX) - { - networkTransform.SyncPositionX = false; - - position.x++; - networkTransform.transform.position = position; - - // If we are synchronizing more than 1 axis (teleporting impacts this too) - if (syncAxis != SyncAxis.SyncPosX && WillAnAxisBeSynchronized(ref networkTransform)) - { - // For the x axis position value We should expect the state to still be considered dirty (more than one axis is being synchronized and we are teleporting) - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - // However, we expect it to not have applied the position x delta - Assert.IsFalse(networkTransformState.HasPositionX); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncPositionY - if (syncPosY) - { - networkTransform.SyncPositionY = false; - - position.y++; - networkTransform.transform.position = position; - if (syncAxis != SyncAxis.SyncPosY && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasPositionY); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncPositionZ - if (syncPosZ) - { - networkTransform.SyncPositionZ = false; - - position.z++; - networkTransform.transform.position = position; - if (syncAxis != SyncAxis.SyncPosZ && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasPositionZ); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncRotAngleX - Now test that we don't synchronize this specific axis as long as we are not using quaternion synchronization - if (syncRotX && m_Rotation == Rotation.Euler) - { - networkTransform.SyncRotAngleX = false; - - rotAngles.x++; - networkTransform.transform.eulerAngles = rotAngles; - if (syncAxis != SyncAxis.SyncRotX && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasRotAngleX); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncRotAngleY - Now test that we don't synchronize this specific axis as long as we are not using quaternion synchronization - if (syncRotY && m_Rotation == Rotation.Euler) - { - networkTransform.SyncRotAngleY = false; - - rotAngles.y++; - networkTransform.transform.eulerAngles = rotAngles; - if (syncAxis != SyncAxis.SyncRotY && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasRotAngleY); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncRotAngleZ - Now test that we don't synchronize this specific axis as long as we are not using quaternion synchronization - if (syncRotZ && m_Rotation == Rotation.Euler) - { - networkTransform.SyncRotAngleZ = false; - - rotAngles.z++; - networkTransform.transform.eulerAngles = rotAngles; - if (syncAxis != SyncAxis.SyncRotZ && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasRotAngleZ); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncScaleX - if (syncScaX) - { - networkTransform.SyncScaleX = false; - - scale.x++; - networkTransform.transform.localScale = scale; - if (syncAxis != SyncAxis.SyncScaleX && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasScaleX); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncScaleY - if (syncScaY) - { - networkTransform.SyncScaleY = false; - - scale.y++; - networkTransform.transform.localScale = scale; - if (syncAxis != SyncAxis.SyncScaleY && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasScaleY); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Reset the NetworkTransformState since teleporting will preserve - // any dirty values - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - // SyncScaleZ - if (syncScaZ) - { - networkTransform.SyncScaleZ = false; - - scale.z++; - networkTransform.transform.localScale = scale; - if (syncAxis != SyncAxis.SyncScaleZ && WillAnAxisBeSynchronized(ref networkTransform)) - { - // We want to start with a fresh NetworkTransformState since it could have other state - // information from the last time we applied the transform - networkTransformState = new NetworkTransform.NetworkTransformState - { - InLocalSpace = inLocalSpace, - IsTeleportingNextFrame = isTeleporting, - }; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - Assert.IsFalse(networkTransformState.HasScaleZ); - } - else - { - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - } - - Object.DestroyImmediate(gameObject); - Object.DestroyImmediate(manager); - } - - - [Test] - public void TestThresholds( - [Values(NetworkTransform.PositionThresholdDefault, 1.0f)] float positionThreshold, - [Values(NetworkTransform.RotAngleThresholdDefault, 1.0f)] float rotAngleThreshold, - [Values(NetworkTransform.ScaleThresholdDefault, 0.5f)] float scaleThreshold) - { - var inLocalSpace = m_TransformSpace == TransformSpace.Local; - var gameObject = new GameObject($"Test-{nameof(NetworkTransformStateTests)}.{nameof(TestThresholds)}"); - var networkTransform = gameObject.AddComponent(); - networkTransform.enabled = false; // do not tick `FixedUpdate()` or `Update()` - - var initialPosition = Vector3.zero; - var initialRotAngles = Vector3.zero; - var initialScale = Vector3.one; - - networkTransform.transform.position = initialPosition; - networkTransform.transform.eulerAngles = initialRotAngles; - networkTransform.transform.localScale = initialScale; - networkTransform.SyncPositionX = true; - networkTransform.SyncPositionY = true; - networkTransform.SyncPositionZ = true; - networkTransform.SyncRotAngleX = true; - networkTransform.SyncRotAngleY = true; - networkTransform.SyncRotAngleZ = true; - networkTransform.SyncScaleX = true; - networkTransform.SyncScaleY = true; - networkTransform.SyncScaleZ = true; - networkTransform.InLocalSpace = inLocalSpace; - networkTransform.PositionThreshold = positionThreshold; - networkTransform.RotAngleThreshold = rotAngleThreshold; - networkTransform.ScaleThreshold = scaleThreshold; - - var networkTransformState = new NetworkTransform.NetworkTransformState - { - PositionX = initialPosition.x, - PositionY = initialPosition.y, - PositionZ = initialPosition.z, - RotAngleX = initialRotAngles.x, - RotAngleY = initialRotAngles.y, - RotAngleZ = initialRotAngles.z, - ScaleX = initialScale.x, - ScaleY = initialScale.y, - ScaleZ = initialScale.z, - InLocalSpace = inLocalSpace - }; - - // Step 1: change properties, expect state to be dirty - { - networkTransform.transform.position = new Vector3(3, 4, 5); - networkTransform.transform.eulerAngles = new Vector3(30, 45, 90); - networkTransform.transform.localScale = new Vector3(1.1f, 0.5f, 2.5f); - - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // Step 2: make changes below and above thresholds - // changes below the threshold should not make `NetworkState` dirty - // changes above the threshold should make `NetworkState` dirty - { - // Position - if (!Mathf.Approximately(positionThreshold, 0.0f)) - { - var position = networkTransform.transform.position; - - // PositionX - { - position.x += positionThreshold / 2; - networkTransform.transform.position = position; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - position.x += positionThreshold * 2; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // PositionY - { - position.y += positionThreshold / 2; - networkTransform.transform.position = position; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - position.y += positionThreshold * 2; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // PositionZ - { - position.z += positionThreshold / 2; - networkTransform.transform.position = position; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - position.z += positionThreshold * 2; - networkTransform.transform.position = position; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // RotAngles - if (!Mathf.Approximately(rotAngleThreshold, 0.0f)) - { - var rotAngles = networkTransform.transform.eulerAngles; - - // RotAngleX - { - rotAngles.x += rotAngleThreshold / 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - rotAngles.x += rotAngleThreshold * 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // RotAngleY - { - rotAngles.y += rotAngleThreshold / 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - rotAngles.y += rotAngleThreshold * 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // RotAngleZ - { - rotAngles.z += rotAngleThreshold / 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - rotAngles.z += rotAngleThreshold * 2; - networkTransform.transform.eulerAngles = rotAngles; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - - // Scale - if (!Mathf.Approximately(scaleThreshold, 0.0f) && inLocalSpace) - { - var scale = networkTransform.transform.localScale; - - // ScaleX - { - scale.x += scaleThreshold / 2; - networkTransform.transform.localScale = scale; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - scale.x += scaleThreshold * 2; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // ScaleY - { - scale.y += scaleThreshold / 2; - networkTransform.transform.localScale = scale; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - scale.y += scaleThreshold * 2; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - - // ScaleZ - { - scale.z += scaleThreshold / 2; - networkTransform.transform.localScale = scale; - Assert.IsFalse(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - - scale.z += scaleThreshold * 2; - networkTransform.transform.localScale = scale; - Assert.IsTrue(networkTransform.ApplyTransformToNetworkState(ref networkTransformState, 0, networkTransform.transform)); - } - } - } - - Object.DestroyImmediate(gameObject); - } - } -} -#endif diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs.meta deleted file mode 100644 index b9ad199..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 89acf93a968324f208e359c47bbf9f9b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs b/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs deleted file mode 100644 index 95ca7e0..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs +++ /dev/null @@ -1,772 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Integration tests for NetworkTransform that will test both - /// server and host operating modes and will test both authoritative - /// models for each operating mode. - /// - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Full)] -#if !MULTIPLAYER_TOOLS - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Half)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.DAHost, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Half)] -#endif - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Euler, Precision.Full)] -#if !MULTIPLAYER_TOOLS - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Euler, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.ServerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Half)] -#endif - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Full)] -#if !MULTIPLAYER_TOOLS - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.None, Rotation.Euler, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.None, Rotation.Quaternion, Precision.Half)] - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Full)] - [TestFixture(HostOrServer.Host, Authority.OwnerAuthority, RotationCompression.QuaternionCompress, Rotation.Quaternion, Precision.Half)] -#endif - internal class NetworkTransformTests : NetworkTransformBase - { - protected const int k_TickRate = 60; - /// - /// Constructor - /// - /// Determines if we are running as a server or host - /// Determines if we are using server or owner authority - public NetworkTransformTests(HostOrServer testWithHost, Authority authority, RotationCompression rotationCompression, Rotation rotation, Precision precision) : - base(testWithHost, authority, rotationCompression, rotation, precision) - { } - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected override uint GetTickRate() - { - return k_TickRate; - } - - private bool m_UseParentingThreshold; - private const float k_ParentingThreshold = 0.25f; - - protected override float GetDeltaVarianceThreshold() - { - if (m_UseParentingThreshold) - { - return k_ParentingThreshold; - } - return base.GetDeltaVarianceThreshold(); - } - - protected override IEnumerator OnSetup() - { - m_UseParentingThreshold = false; - return base.OnSetup(); - } - - /// - /// Handles validating the local space values match the original local space values. - /// If not, it generates a message containing the axial values that did not match - /// the target/start local space values. - /// - private void AllChildrenLocalTransformValuesMatch(bool useSubChild, ChildrenTransformCheckType checkType) - { - // We don't assert on timeout here because we want to log this information during PostAllChildrenLocalTransformValuesMatch - var success = WaitForConditionOrTimeOutWithTimeTravel(() => AllInstancesKeptLocalTransformValues(useSubChild), (int)GetTickRate() * 2); - m_InfoMessage.Clear(); - m_InfoMessage.AppendLine($"[{checkType}][{useSubChild}] Timed out waiting for all children to have the correct local space values:\n"); - if (!success) - { - // If we timed out, then wait for 4 ticks to assure all data has been synchronized before declaring this a failed test. - for (int j = 0; j < 4; j++) - { - var instances = useSubChild ? ChildObjectComponent.SubInstances : ChildObjectComponent.Instances; - success = PostAllChildrenLocalTransformValuesMatch(useSubChild); - TimeTravelAdvanceTick(); - } - } - - if (!success) - { - Assert.True(success, m_InfoMessage.ToString()); - } - } - -#if !MULTIPLAYER_TOOLS - - private void UpdateTransformLocal(Components.NetworkTransform networkTransformTestComponent) - { - networkTransformTestComponent.transform.localPosition += GetRandomVector3(0.5f, 2.0f); - var rotation = networkTransformTestComponent.transform.localRotation; - var eulerRotation = rotation.eulerAngles; - eulerRotation += GetRandomVector3(0.5f, 5.0f); - rotation.eulerAngles = eulerRotation; - networkTransformTestComponent.transform.localRotation = rotation; - } - - private void UpdateTransformWorld(Components.NetworkTransform networkTransformTestComponent) - { - networkTransformTestComponent.transform.position += GetRandomVector3(0.5f, 2.0f); - var rotation = networkTransformTestComponent.transform.rotation; - var eulerRotation = rotation.eulerAngles; - eulerRotation += GetRandomVector3(0.5f, 5.0f); - rotation.eulerAngles = eulerRotation; - networkTransformTestComponent.transform.rotation = rotation; - } - - /// - /// This test validates the SwitchTransformSpaceWhenParented setting under all network topologies - /// - [Test] - public void SwitchTransformSpaceWhenParentedTest([Values(0.5f, 1.0f, 5.0f)] float scale) - { - m_UseParentingThreshold = true; - // Get the NetworkManager that will have authority in order to spawn with the correct authority - var isServerAuthority = m_Authority == Authority.ServerAuthority; - var authorityNetworkManager = m_ServerNetworkManager; - if (!isServerAuthority) - { - authorityNetworkManager = m_ClientNetworkManagers[0]; - } - - var childAuthorityNetworkManager = m_ClientNetworkManagers[0]; - if (!isServerAuthority) - { - childAuthorityNetworkManager = m_ServerNetworkManager; - } - - // Spawn a parent and children - ChildObjectComponent.HasSubChild = true; - // Modify our prefabs for this specific test - m_ParentObject.GetComponent().TickSyncChildren = true; - m_ChildObject.GetComponent().SwitchTransformSpaceWhenParented = true; - m_ChildObject.GetComponent().TickSyncChildren = true; - m_SubChildObject.GetComponent().SwitchTransformSpaceWhenParented = true; - m_SubChildObject.GetComponent().TickSyncChildren = true; - m_ChildObject.AllowOwnerToParent = true; - m_SubChildObject.AllowOwnerToParent = true; - - - var authoritySideParent = SpawnObject(m_ParentObject.gameObject, authorityNetworkManager).GetComponent(); - var authoritySideChild = SpawnObject(m_ChildObject.gameObject, childAuthorityNetworkManager).GetComponent(); - var authoritySideSubChild = SpawnObject(m_SubChildObject.gameObject, childAuthorityNetworkManager).GetComponent(); - - // Assure all of the child object instances are spawned before proceeding to parenting - var success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned); - Assert.True(success, "Timed out waiting for all child instances to be spawned!"); - - // Get the owner instance if in client-server mode with owner authority - if (m_Authority == Authority.OwnerAuthority && !m_DistributedAuthority) - { - authoritySideParent = s_GlobalNetworkObjects[authoritySideParent.OwnerClientId][authoritySideParent.NetworkObjectId]; - authoritySideChild = s_GlobalNetworkObjects[authoritySideChild.OwnerClientId][authoritySideChild.NetworkObjectId]; - authoritySideSubChild = s_GlobalNetworkObjects[authoritySideSubChild.OwnerClientId][authoritySideSubChild.NetworkObjectId]; - } - - // Get the authority parent and child instances - m_AuthorityParentObject = NetworkTransformTestComponent.AuthorityInstance.NetworkObject; - m_AuthorityChildObject = ChildObjectComponent.AuthorityInstance.NetworkObject; - m_AuthoritySubChildObject = ChildObjectComponent.AuthoritySubInstance.NetworkObject; - - // The child NetworkTransform will use world space when world position stays and - // local space when world position does not stay when parenting. - ChildObjectComponent.AuthorityInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthorityInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthorityInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - ChildObjectComponent.AuthoritySubInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - // Set whether we are interpolating or not - m_AuthorityParentNetworkTransform = m_AuthorityParentObject.GetComponent(); - m_AuthorityParentNetworkTransform.Interpolate = true; - m_AuthorityChildNetworkTransform = m_AuthorityChildObject.GetComponent(); - m_AuthorityChildNetworkTransform.Interpolate = true; - m_AuthoritySubChildNetworkTransform = m_AuthoritySubChildObject.GetComponent(); - m_AuthoritySubChildNetworkTransform.Interpolate = true; - - // Apply a scale to the parent object to make sure the scale on the child is properly updated on - // non-authority instances. - var halfScale = scale * 0.5f; - m_AuthorityParentObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthorityChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthoritySubChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - - // Allow one tick for authority to update these changes - TimeTravelAdvanceTick(); - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - - Assert.True(success, "All transform values did not match prior to parenting!"); - - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - - Assert.True(success, "All transform values did not match prior to parenting!"); - - // Move things around while parenting and removing the parent - // Not the absolute "perfect" test, but it validates the clients all synchronize - // parenting and transform values. - for (int i = 0; i < 30; i++) - { - // Provide two network ticks for interpolation to finalize - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // This validates each child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Connected_Clients); - - // This validates each sub-child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Connected_Clients); - // Parent while in motion - if (i == 5) - { - // Parent the child under the parent with the current world position stays setting - Assert.True(authoritySideChild.TrySetParent(authoritySideParent.transform), $"[Child][Client-{authoritySideChild.NetworkManagerOwner.LocalClientId}] Failed to set child's parent!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllFirstLevelChildObjectInstancesHaveChild, 300); - Assert.True(success, "Timed out waiting for all instances to have parented a child!"); - } - - if (i == 10) - { - // Parent the sub-child under the child with the current world position stays setting - Assert.True(authoritySideSubChild.TrySetParent(authoritySideChild.transform), $"[Sub-Child][Client-{authoritySideSubChild.NetworkManagerOwner.LocalClientId}] Failed to set sub-child's parent!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild, 300); - Assert.True(success, "Timed out waiting for all instances to have parented a child!"); - } - - if (i == 15) - { - // Verify that a late joining client will synchronize to the parented NetworkObjects properly - CreateAndStartNewClientWithTimeTravel(); - - // Assure all of the child object instances are spawned (basically for the newly connected client) - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned, 300); - Assert.True(success, "Timed out waiting for all child instances to be spawned!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild, 300); - Assert.True(success, "Timed out waiting for all instances to have parented a child!"); - - // This validates each child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Late_Join_Client); - - // This validates each sub-child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Late_Join_Client); - } - - if (i == 20) - { - // Remove the parent - Assert.True(authoritySideSubChild.TryRemoveParent(), $"[Sub-Child][Client-{authoritySideSubChild.NetworkManagerOwner.LocalClientId}] Failed to set sub-child's parent!"); - - // This waits for all child instances to have the parent removed - success = WaitForConditionOrTimeOutWithTimeTravel(AllSubChildObjectInstancesHaveNoParent, 300); - Assert.True(success, "Timed out waiting for all instances remove the parent!"); - } - - if (i == 25) - { - // Parent the child under the parent with the current world position stays setting - Assert.True(authoritySideChild.TryRemoveParent(), $"[Child][Client-{authoritySideChild.NetworkManagerOwner.LocalClientId}] Failed to remove parent!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllFirstLevelChildObjectInstancesHaveNoParent, 300); - Assert.True(success, "Timed out waiting for all instances remove the parent!"); - } - UpdateTransformWorld(m_AuthorityParentNetworkTransform); - if (m_AuthorityChildNetworkTransform.InLocalSpace) - { - UpdateTransformLocal(m_AuthorityChildNetworkTransform); - } - else - { - UpdateTransformWorld(m_AuthorityChildNetworkTransform); - } - - if (m_AuthoritySubChildNetworkTransform.InLocalSpace) - { - UpdateTransformLocal(m_AuthoritySubChildNetworkTransform); - } - else - { - UpdateTransformWorld(m_AuthoritySubChildNetworkTransform); - } - } - - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches, 300); - - Assert.True(success, "All transform values did not match prior to parenting!"); - - // Revert the modifications made for this specific test - m_ParentObject.GetComponent().TickSyncChildren = false; - m_ChildObject.GetComponent().SwitchTransformSpaceWhenParented = false; - m_ChildObject.GetComponent().TickSyncChildren = false; - m_ChildObject.AllowOwnerToParent = false; - m_SubChildObject.AllowOwnerToParent = false; - m_SubChildObject.GetComponent().SwitchTransformSpaceWhenParented = false; - m_SubChildObject.GetComponent().TickSyncChildren = false; - } - - - /// - /// Validates that transform values remain the same when a NetworkTransform is - /// parented under another NetworkTransform under all of the possible axial conditions - /// as well as when the parent has a varying scale. - /// - [Test] - public void ParentedNetworkTransformTest([Values] Interpolation interpolation, [Values] bool worldPositionStays, [Values(0.5f, 1.0f, 5.0f)] float scale) - { - m_UseParentingThreshold = true; - // Get the NetworkManager that will have authority in order to spawn with the correct authority - var isServerAuthority = m_Authority == Authority.ServerAuthority; - var authorityNetworkManager = m_ServerNetworkManager; - if (!isServerAuthority) - { - authorityNetworkManager = m_ClientNetworkManagers[0]; - } - - // Spawn a parent and children - ChildObjectComponent.HasSubChild = true; - var serverSideParent = SpawnObject(m_ParentObject.gameObject, authorityNetworkManager).GetComponent(); - var serverSideChild = SpawnObject(m_ChildObject.gameObject, authorityNetworkManager).GetComponent(); - var serverSideSubChild = SpawnObject(m_SubChildObject.gameObject, authorityNetworkManager).GetComponent(); - - // Assure all of the child object instances are spawned before proceeding to parenting - var success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned); - Assert.True(success, "Timed out waiting for all child instances to be spawned!"); - - // Get the authority parent and child instances - m_AuthorityParentObject = NetworkTransformTestComponent.AuthorityInstance.NetworkObject; - m_AuthorityChildObject = ChildObjectComponent.AuthorityInstance.NetworkObject; - m_AuthoritySubChildObject = ChildObjectComponent.AuthoritySubInstance.NetworkObject; - - // The child NetworkTransform will use world space when world position stays and - // local space when world position does not stay when parenting. - ChildObjectComponent.AuthorityInstance.InLocalSpace = !worldPositionStays; - ChildObjectComponent.AuthorityInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthorityInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthorityInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - ChildObjectComponent.AuthoritySubInstance.InLocalSpace = !worldPositionStays; - ChildObjectComponent.AuthoritySubInstance.UseHalfFloatPrecision = m_Precision == Precision.Half; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionSynchronization = m_Rotation == Rotation.Quaternion; - ChildObjectComponent.AuthoritySubInstance.UseQuaternionCompression = m_RotationCompression == RotationCompression.QuaternionCompress; - - // Set whether we are interpolating or not - m_AuthorityParentNetworkTransform = m_AuthorityParentObject.GetComponent(); - m_AuthorityParentNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthorityChildNetworkTransform = m_AuthorityChildObject.GetComponent(); - m_AuthorityChildNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritySubChildNetworkTransform = m_AuthoritySubChildObject.GetComponent(); - m_AuthoritySubChildNetworkTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - - - // Apply a scale to the parent object to make sure the scale on the child is properly updated on - // non-authority instances. - var halfScale = scale * 0.5f; - m_AuthorityParentObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthorityChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - m_AuthoritySubChildObject.transform.localScale = GetRandomVector3(scale - halfScale, scale + halfScale); - - // Allow one tick for authority to update these changes - TimeTravelAdvanceTick(); - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - - Assert.True(success, "All transform values did not match prior to parenting!"); - - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - - Assert.True(success, "All transform values did not match prior to parenting!"); - - // Parent the child under the parent with the current world position stays setting - Assert.True(serverSideChild.TrySetParent(serverSideParent.transform, worldPositionStays), "[Server-Side Child] Failed to set child's parent!"); - - // Parent the sub-child under the child with the current world position stays setting - Assert.True(serverSideSubChild.TrySetParent(serverSideChild.transform, worldPositionStays), "[Server-Side SubChild] Failed to set sub-child's parent!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild); - Assert.True(success, "Timed out waiting for all instances to have parented a child!"); - - // Provide two network ticks for interpolation to finalize - TimeTravelAdvanceTick(); - TimeTravelAdvanceTick(); - - // This validates each child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Connected_Clients); - - // This validates each sub-child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Connected_Clients); - - // Verify that a late joining client will synchronize to the parented NetworkObjects properly - CreateAndStartNewClientWithTimeTravel(); - - // Assure all of the child object instances are spawned (basically for the newly connected client) - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesAreSpawned); - Assert.True(success, "Timed out waiting for all child instances to be spawned!"); - - // This waits for all child instances to be parented - success = WaitForConditionOrTimeOutWithTimeTravel(AllChildObjectInstancesHaveChild); - Assert.True(success, "Timed out waiting for all instances to have parented a child!"); - - // This validates each child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(false, ChildrenTransformCheckType.Late_Join_Client); - - // This validates each sub-child instance has preserved their local space values - AllChildrenLocalTransformValuesMatch(true, ChildrenTransformCheckType.Late_Join_Client); - } - - /// - /// This validates that multiple changes can occur within the same tick or over - /// several ticks while still keeping non-authoritative instances synchronized. - /// - /// - /// When testing < 3 axis: Interpolation is disabled and only 3 delta updates are applied per unique test - /// When testing 3 axis: Interpolation is enabled, sometimes an axis is intentionally excluded during a - /// delta update, and it runs through 8 delta updates per unique test. - /// - [Test] - public void NetworkTransformMultipleChangesOverTime([Values] TransformSpace testLocalTransform, [Values] OverrideState overideState, [Values] Axis axis) - { - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - bool axisX = axis == Axis.X || axis == Axis.XY || axis == Axis.XZ || axis == Axis.XYZ; - bool axisY = axis == Axis.Y || axis == Axis.XY || axis == Axis.YZ || axis == Axis.XYZ; - bool axisZ = axis == Axis.Z || axis == Axis.XZ || axis == Axis.YZ || axis == Axis.XYZ; - - var axisCount = axisX ? 1 : 0; - axisCount += axisY ? 1 : 0; - axisCount += axisZ ? 1 : 0; - - // Enable interpolation when all 3 axis are selected to make sure we are synchronizing properly - // when interpolation is enabled. - m_AuthoritativeTransform.Interpolate = axisCount == 3 ? true : false; - - m_CurrentAxis = axis; - - m_AuthoritativeTransform.SyncPositionX = axisX; - m_AuthoritativeTransform.SyncPositionY = axisY; - m_AuthoritativeTransform.SyncPositionZ = axisZ; - - if (!m_AuthoritativeTransform.UseQuaternionSynchronization) - { - m_AuthoritativeTransform.SyncRotAngleX = axisX; - m_AuthoritativeTransform.SyncRotAngleY = axisY; - m_AuthoritativeTransform.SyncRotAngleZ = axisZ; - } - else - { - // This is not required for usage (setting the value should not matter when quaternion synchronization is enabled) - // but is required for this test so we don't get a failure on an axis that is marked to not be synchronized when - // validating the authority's values on non-authority instances. - m_AuthoritativeTransform.SyncRotAngleX = true; - m_AuthoritativeTransform.SyncRotAngleY = true; - m_AuthoritativeTransform.SyncRotAngleZ = true; - } - - m_AuthoritativeTransform.SyncScaleX = axisX; - m_AuthoritativeTransform.SyncScaleY = axisY; - m_AuthoritativeTransform.SyncScaleZ = axisZ; - - var positionStart = GetRandomVector3(0.25f, 1.75f); - var rotationStart = GetRandomVector3(1f, 15f); - var scaleStart = GetRandomVector3(0.25f, 2.0f); - var position = positionStart; - var rotation = rotationStart; - var scale = scaleStart; - var success = false; - - m_AuthoritativeTransform.StatePushed = false; - // Wait for the deltas to be pushed - WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed); - // Allow the precision settings to propagate first as changing precision - // causes a teleport event to occur - TimeTravelAdvanceTick(); - var iterations = axisCount == 3 ? k_PositionRotationScaleIterations3Axis : k_PositionRotationScaleIterations; - - // Move and rotate within the same tick, validate the non-authoritative instance updates - // to each set of changes. Repeat several times. - for (int i = 0; i < iterations; i++) - { - // Always reset this per delta update pass - m_AxisExcluded = false; - var deltaPositionDelta = GetRandomVector3(-1.5f, 1.5f); - var deltaRotationDelta = GetRandomVector3(-3.5f, 3.5f); - var deltaScaleDelta = GetRandomVector3(-0.5f, 0.5f); - - m_NonAuthoritativeTransform.StateUpdated = false; - m_AuthoritativeTransform.StatePushed = false; - - // With two or more axis, excluding one of them while chaging another will validate that - // full precision updates are maintaining their target state value(s) to interpolate towards - if (axisCount == 3) - { - position += RandomlyExcludeAxis(deltaPositionDelta); - rotation += RandomlyExcludeAxis(deltaRotationDelta); - scale += RandomlyExcludeAxis(deltaScaleDelta); - } - else - { - position += deltaPositionDelta; - rotation += deltaRotationDelta; - scale += deltaScaleDelta; - } - - // Apply delta between ticks - MoveRotateAndScaleAuthority(position, rotation, scale, overideState); - - // Wait for the deltas to be pushed - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed && m_NonAuthoritativeTransform.StateUpdated), $"[Non-Interpolate {i}] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed}) or state to be updated ({m_NonAuthoritativeTransform.StateUpdated})!"); - - // For 3 axis, we will skip validating that the non-authority interpolates to its target point at least once. - // This will validate that non-authoritative updates are maintaining their target state axis values if only 2 - // of the axis are being updated to assure interpolation maintains the targeted axial value per axis. - // For 2 and 1 axis tests we always validate per delta update - if (m_AxisExcluded || axisCount < 3) - { - // Wait for deltas to synchronize on non-authoritative side - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - // Provide additional debug info about what failed (if it fails) - if (!success) - { - m_EnableVerboseDebug = true; - success = PositionRotationScaleMatches(); - m_EnableVerboseDebug = false; - } - Assert.True(success, $"[Non-Interpolate {i}] Timed out waiting for non-authority to match authority's position or rotation"); - } - } - - if (axisCount == 3) - { - // As a final test, wait for deltas to synchronize on non-authoritative side to assure it interpolates to th - success = WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - // Provide additional debug info about what failed (if it fails) - if (!success) - { - m_EnableVerboseDebug = true; - success = PositionRotationScaleMatches(); - m_EnableVerboseDebug = false; - } - Assert.True(success, $"Timed out waiting for non-authority to match authority's position or rotation"); - } - } - - /// - /// Checks scale of a late joining client for all instances of the late joining client's player - /// - [Test] - public void LateJoiningPlayerInitialScaleValues([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation, [Values] OverrideState overideState) - { - var overrideUpdate = overideState == OverrideState.CommitToTransform; - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - - var position = GetRandomVector3(0.25f, 1.75f); - var rotation = GetRandomVector3(1f, 45f); - var scale = GetRandomVector3(0.25f, 2.0f); - - // Make some changes to the currently connected clients - m_NonAuthoritativeTransform.StateUpdated = false; - m_AuthoritativeTransform.StatePushed = false; - MoveRotateAndScaleAuthority(position, rotation, scale, overideState); - - // Wait for the deltas to be pushed and updated - var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed && m_NonAuthoritativeTransform.StateUpdated); - Assert.True(success, $"[Interpolation {k_PositionRotationScaleIterations}] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed}) or state to be updated ({m_NonAuthoritativeTransform.StateUpdated})!"); - - WaitForConditionOrTimeOutWithTimeTravel(PositionRotationScaleMatches); - - // Validate the use of the prefab's transform values as opposed to the replicated state (which now is only the last deltas) - CreateAndStartNewClientWithTimeTravel(); - var newClientNetworkManager = m_ClientNetworkManagers[NumberOfClients]; - foreach (var playerRelativeEntry in m_PlayerNetworkObjects) - { - foreach (var playerInstanceEntry in playerRelativeEntry.Value) - { - var playerInstance = playerInstanceEntry.Value; - if (newClientNetworkManager.LocalClientId == playerInstance.OwnerClientId) - { - Assert.IsTrue(Approximately(m_PlayerPrefab.transform.localScale, playerInstance.transform.localScale), $"{playerInstance.name}'s cloned instance's scale does not match original scale!\n" + - $"[ClientId-{playerRelativeEntry.Key} Relative] Player-{playerInstance.OwnerClientId}'s LocalScale ({playerInstance.transform.localScale}) vs Target Scale ({m_PlayerPrefab.transform.localScale})"); - } - } - } - } -#endif - - /// - /// Tests changing all axial values one at a time. - /// These tests are performed: - /// - While in local space and world space - /// - While interpolation is enabled and disabled - /// - Using the TryCommitTransformToServer "override" that can be used - /// from a child derived or external class. - /// - [Test] - public void TestAuthoritativeTransformChangeOneAtATime([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation, [Values] OverrideState overideState) - { - var overrideUpdate = overideState == OverrideState.CommitToTransform; - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; - - // test position - var authPlayerTransform = overrideUpdate ? m_OwnerTransform.transform : m_AuthoritativeTransform.transform; - - Assert.AreEqual(Vector3.zero, m_NonAuthoritativeTransform.transform.position, "server side pos should be zero at first"); // sanity check - - TimeTravelAdvanceTick(); - TimeTravelToNextTick(); - - m_AuthoritativeTransform.StatePushed = false; - var nextPosition = GetRandomVector3(2f, 30f); - - switch (overideState) - { - case OverrideState.Update: - { - m_AuthoritativeTransform.transform.position = nextPosition; - break; - } - case OverrideState.SetState: - { - m_OwnerTransform.SetState(nextPosition, null, null); - break; - } - case OverrideState.CommitToTransform: - { - m_OwnerTransform.transform.position = nextPosition; - m_OwnerTransform.CommitToTransform(); - break; - } - } - - bool success; - if (overideState == OverrideState.CommitToTransform) - { - // Wait for the deltas to be pushed - success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed, 600); - Assert.True(success, $"[Position] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed})!"); - } - - success = WaitForConditionOrTimeOutWithTimeTravel(() => PositionsMatch(), 600); - Assert.True(success, $"Timed out waiting for positions to match {m_AuthoritativeTransform.transform.position} | {m_NonAuthoritativeTransform.transform.position}"); - - // test rotation - Assert.AreEqual(Quaternion.identity, m_NonAuthoritativeTransform.transform.rotation, "wrong initial value for rotation"); // sanity check - - m_AuthoritativeTransform.StatePushed = false; - var nextRotation = Quaternion.Euler(GetRandomVector3(5, 60)); // using euler angles instead of quaternions directly to really see issues users might encounter - switch (overideState) - { - case OverrideState.Update: - { - m_AuthoritativeTransform.transform.rotation = nextRotation; - break; - } - case OverrideState.SetState: - { - m_OwnerTransform.SetState(null, nextRotation, null); - break; - } - case OverrideState.CommitToTransform: - { - m_OwnerTransform.transform.rotation = nextRotation; - m_OwnerTransform.CommitToTransform(); - break; - } - } - - if (overideState == OverrideState.CommitToTransform) - { - // Wait for the deltas to be pushed - success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed, 600); - Assert.True(success, $"[Rotation] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed})!"); - } - - // Make sure the values match - success = WaitForConditionOrTimeOutWithTimeTravel(() => RotationsMatch(), 600); - Assert.True(success, $"Timed out waiting for rotations to match"); - - m_AuthoritativeTransform.StatePushed = false; - var nextScale = GetRandomVector3(1, 6); - - switch (overideState) - { - case OverrideState.Update: - { - m_AuthoritativeTransform.transform.localScale = nextScale; - break; - } - case OverrideState.SetState: - { - m_OwnerTransform.SetState(null, null, nextScale); - break; - } - case OverrideState.CommitToTransform: - { - m_OwnerTransform.transform.localScale = nextScale; - m_OwnerTransform.CommitToTransform(); - break; - } - } - - if (overideState == OverrideState.CommitToTransform) - { - // Wait for the deltas to be pushed - success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed, 600); - Assert.True(success, $"[Rotation] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed})!"); - } - - // Make sure the scale values match - success = WaitForConditionOrTimeOutWithTimeTravel(() => ScaleValuesMatch(), 600); - Assert.True(success, $"Timed out waiting for scale values to match"); - } - - /// - /// The tests teleporting with and without interpolation - /// - [Test] - public void TeleportTest([Values] Interpolation interpolation) - { - m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; - var authTransform = m_AuthoritativeTransform.transform; - var nonAuthPosition = m_NonAuthoritativeTransform.transform.position; - var currentTick = m_AuthoritativeTransform.NetworkManager.ServerTime.Tick; - m_DetectedPotentialInterpolatedTeleport = 0.0f; - var teleportDestination = GetRandomVector3(50.0f, 200.0f); - m_NonAuthoritativeTransform.StateUpdated = false; - m_AuthoritativeTransform.StatePushed = false; - m_AuthoritativeTransform.Teleport(teleportDestination, authTransform.rotation, authTransform.localScale); - - // Wait for the deltas to be pushed and updated - var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_AuthoritativeTransform.StatePushed && m_NonAuthoritativeTransform.StateUpdated); - Assert.True(success, $"[Teleport] Timed out waiting for state to be pushed ({m_AuthoritativeTransform.StatePushed}) or state to be updated ({m_NonAuthoritativeTransform.StateUpdated})!"); - - SimulateOneFrame(); - Assert.True(TeleportPositionMatches(nonAuthPosition), $"NonAuthoritative position ({m_NonAuthoritativeTransform.GetSpaceRelativePosition()}) is not the same as the destination position {teleportDestination}!"); - - var targetDistance = 0.0f; - if (!Approximately(m_DetectedPotentialInterpolatedTeleport, 0.0f)) - { - targetDistance = Mathf.Abs(Vector3.Distance(nonAuthPosition, teleportDestination)); - } - Assert.IsTrue(Approximately(m_DetectedPotentialInterpolatedTeleport, 0.0f), $"Detected possible interpolation on non-authority side! NonAuthority distance: {m_DetectedPotentialInterpolatedTeleport} | Target distance: {targetDistance}"); - } - - } -} diff --git a/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta b/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta deleted file mode 100644 index d5b2726..0000000 --- a/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: cf4ff0d6357bb4474a404b9ce52b22ad -timeCreated: 1620872927 \ No newline at end of file diff --git a/Tests/Runtime/NetworkTransformAnticipationTests.cs b/Tests/Runtime/NetworkTransformAnticipationTests.cs deleted file mode 100644 index c4921d1..0000000 --- a/Tests/Runtime/NetworkTransformAnticipationTests.cs +++ /dev/null @@ -1,520 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkTransformAnticipationComponent : NetworkBehaviour - { - [Rpc(SendTo.Server)] - public void MoveRpc(Vector3 newPosition) - { - transform.position = newPosition; - } - - [Rpc(SendTo.Server)] - public void ScaleRpc(Vector3 newScale) - { - transform.localScale = newScale; - } - - [Rpc(SendTo.Server)] - public void RotateRpc(Quaternion newRotation) - { - transform.rotation = newRotation; - } - - public bool ShouldSmooth = false; - public bool ShouldMove = false; - - public override void OnReanticipate(double lastRoundTripTime) - { - var transform_ = GetComponent(); - if (transform_.ShouldReanticipate) - { - if (ShouldSmooth) - { - transform_.Smooth(transform_.PreviousAnticipatedState, transform_.AuthoritativeState, 1); - } - - if (ShouldMove) - { - transform_.AnticipateMove(transform_.AuthoritativeState.Position + new Vector3(0, 5, 0)); - - } - } - } - } - - internal class NetworkTransformAnticipationTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected override void OnPlayerPrefabGameObjectCreated() - { - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - } - - protected override void OnTimeTravelServerAndClientsConnected() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - var otherClientComponent = GetOtherClientComponent(); - - serverComponent.transform.position = Vector3.zero; - serverComponent.transform.localScale = Vector3.one; - serverComponent.transform.rotation = Quaternion.LookRotation(Vector3.forward); - testComponent.transform.position = Vector3.zero; - testComponent.transform.localScale = Vector3.one; - testComponent.transform.rotation = Quaternion.LookRotation(Vector3.forward); - otherClientComponent.transform.position = Vector3.zero; - otherClientComponent.transform.localScale = Vector3.one; - otherClientComponent.transform.rotation = Quaternion.LookRotation(Vector3.forward); - } - - public AnticipatedNetworkTransform GetTestComponent() - { - return m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - } - - public AnticipatedNetworkTransform GetServerComponent() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.NetworkManager == m_ServerNetworkManager && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId) - { - return obj; - } - } - - return null; - } - - public AnticipatedNetworkTransform GetOtherClientComponent() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.NetworkManager == m_ClientNetworkManagers[1] && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId) - { - return obj; - } - } - - return null; - } - - [Test] - public void WhenAnticipating_ValueChangesImmediately() - { - var testComponent = GetTestComponent(); - - testComponent.AnticipateMove(new Vector3(0, 1, 2)); - testComponent.AnticipateScale(new Vector3(1, 2, 3)); - testComponent.AnticipateRotate(Quaternion.LookRotation(new Vector3(2, 3, 4))); - - Assert.AreEqual(new Vector3(0, 1, 2), testComponent.transform.position); - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.transform.localScale); - Assert.AreEqual(Quaternion.LookRotation(new Vector3(2, 3, 4)), testComponent.transform.rotation); - - Assert.AreEqual(new Vector3(0, 1, 2), testComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.AnticipatedState.Scale); - Assert.AreEqual(Quaternion.LookRotation(new Vector3(2, 3, 4)), testComponent.AnticipatedState.Rotation); - - } - - [Test] - public void WhenAnticipating_AuthoritativeValueDoesNotChange() - { - var testComponent = GetTestComponent(); - - var startPosition = testComponent.transform.position; - var startScale = testComponent.transform.localScale; - var startRotation = testComponent.transform.rotation; - - testComponent.AnticipateMove(new Vector3(0, 1, 2)); - testComponent.AnticipateScale(new Vector3(1, 2, 3)); - testComponent.AnticipateRotate(Quaternion.LookRotation(new Vector3(2, 3, 4))); - - Assert.AreEqual(startPosition, testComponent.AuthoritativeState.Position); - Assert.AreEqual(startScale, testComponent.AuthoritativeState.Scale); - Assert.AreEqual(startRotation, testComponent.AuthoritativeState.Rotation); - } - - [Test] - public void WhenAnticipating_ServerDoesNotChange() - { - var testComponent = GetTestComponent(); - - var startPosition = testComponent.transform.position; - var startScale = testComponent.transform.localScale; - var startRotation = testComponent.transform.rotation; - - testComponent.AnticipateMove(new Vector3(0, 1, 2)); - testComponent.AnticipateScale(new Vector3(1, 2, 3)); - testComponent.AnticipateRotate(Quaternion.LookRotation(new Vector3(2, 3, 4))); - - var serverComponent = GetServerComponent(); - - Assert.AreEqual(startPosition, serverComponent.AuthoritativeState.Position); - Assert.AreEqual(startScale, serverComponent.AuthoritativeState.Scale); - Assert.AreEqual(startRotation, serverComponent.AuthoritativeState.Rotation); - Assert.AreEqual(startPosition, serverComponent.AnticipatedState.Position); - Assert.AreEqual(startScale, serverComponent.AnticipatedState.Scale); - Assert.AreEqual(startRotation, serverComponent.AnticipatedState.Rotation); - - TimeTravel(2, 120); - - Assert.AreEqual(startPosition, serverComponent.AuthoritativeState.Position); - Assert.AreEqual(startScale, serverComponent.AuthoritativeState.Scale); - Assert.AreEqual(startRotation, serverComponent.AuthoritativeState.Rotation); - Assert.AreEqual(startPosition, serverComponent.AnticipatedState.Position); - Assert.AreEqual(startScale, serverComponent.AnticipatedState.Scale); - Assert.AreEqual(startRotation, serverComponent.AnticipatedState.Rotation); - } - - [Test] - public void WhenAnticipating_OtherClientDoesNotChange() - { - var testComponent = GetTestComponent(); - - var startPosition = testComponent.transform.position; - var startScale = testComponent.transform.localScale; - var startRotation = testComponent.transform.rotation; - - testComponent.AnticipateMove(new Vector3(0, 1, 2)); - testComponent.AnticipateScale(new Vector3(1, 2, 3)); - testComponent.AnticipateRotate(Quaternion.LookRotation(new Vector3(2, 3, 4))); - - var otherClientComponent = GetOtherClientComponent(); - - Assert.AreEqual(startPosition, otherClientComponent.AuthoritativeState.Position); - Assert.AreEqual(startScale, otherClientComponent.AuthoritativeState.Scale); - Assert.AreEqual(startRotation, otherClientComponent.AuthoritativeState.Rotation); - Assert.AreEqual(startPosition, otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(startScale, otherClientComponent.AnticipatedState.Scale); - Assert.AreEqual(startRotation, otherClientComponent.AnticipatedState.Rotation); - - TimeTravel(2, 120); - - Assert.AreEqual(startPosition, otherClientComponent.AuthoritativeState.Position); - Assert.AreEqual(startScale, otherClientComponent.AuthoritativeState.Scale); - Assert.AreEqual(startRotation, otherClientComponent.AuthoritativeState.Rotation); - Assert.AreEqual(startPosition, otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(startScale, otherClientComponent.AnticipatedState.Scale); - Assert.AreEqual(startRotation, otherClientComponent.AnticipatedState.Rotation); - } - - [Test] - public void WhenServerChangesSnapValue_ValuesAreUpdated() - { - var testComponent = GetTestComponent(); - var serverComponent = GetServerComponent(); - serverComponent.Interpolate = false; - - testComponent.AnticipateMove(new Vector3(0, 1, 2)); - testComponent.AnticipateScale(new Vector3(1, 2, 3)); - testComponent.AnticipateRotate(Quaternion.LookRotation(new Vector3(2, 3, 4))); - - var rpcComponent = testComponent.GetComponent(); - rpcComponent.MoveRpc(new Vector3(2, 3, 4)); - - WaitForMessageReceivedWithTimeTravel(new List { m_ServerNetworkManager }); - var otherClientComponent = GetOtherClientComponent(); - - WaitForConditionOrTimeOutWithTimeTravel(() => testComponent.AuthoritativeState.Position == serverComponent.transform.position && otherClientComponent.AuthoritativeState.Position == serverComponent.transform.position); - - Assert.AreEqual(serverComponent.transform.position, testComponent.transform.position); - Assert.AreEqual(serverComponent.transform.position, testComponent.AnticipatedState.Position); - Assert.AreEqual(serverComponent.transform.position, testComponent.AuthoritativeState.Position); - - Assert.AreEqual(serverComponent.transform.position, otherClientComponent.transform.position); - Assert.AreEqual(serverComponent.transform.position, otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(serverComponent.transform.position, otherClientComponent.AuthoritativeState.Position); - } - - public void AssertQuaternionsAreEquivalent(Quaternion a, Quaternion b) - { - var aAngles = a.eulerAngles; - var bAngles = b.eulerAngles; - Assert.AreEqual(aAngles.x, bAngles.x, 0.001, $"Quaternions were not equal. Expected: {a}, but was {b}"); - Assert.AreEqual(aAngles.y, bAngles.y, 0.001, $"Quaternions were not equal. Expected: {a}, but was {b}"); - Assert.AreEqual(aAngles.z, bAngles.z, 0.001, $"Quaternions were not equal. Expected: {a}, but was {b}"); - } - public void AssertVectorsAreEquivalent(Vector3 a, Vector3 b) - { - Assert.AreEqual(a.x, b.x, 0.001, $"Vectors were not equal. Expected: {a}, but was {b}"); - Assert.AreEqual(a.y, b.y, 0.001, $"Vectors were not equal. Expected: {a}, but was {b}"); - Assert.AreEqual(a.z, b.z, 0.001, $"Vectors were not equal. Expected: {a}, but was {b}"); - } - - [Test] - public void WhenServerChangesSmoothValue_ValuesAreLerped() - { - var testComponent = GetTestComponent(); - var otherClientComponent = GetOtherClientComponent(); - - testComponent.StaleDataHandling = StaleDataHandling.Ignore; - otherClientComponent.StaleDataHandling = StaleDataHandling.Ignore; - - var serverComponent = GetServerComponent(); - serverComponent.Interpolate = false; - - testComponent.GetComponent().ShouldSmooth = true; - otherClientComponent.GetComponent().ShouldSmooth = true; - - var startPosition = testComponent.transform.position; - var startScale = testComponent.transform.localScale; - var startRotation = testComponent.transform.rotation; - var anticipePosition = new Vector3(0, 1, 2); - var anticipeScale = new Vector3(1, 2, 3); - var anticipeRotation = Quaternion.LookRotation(new Vector3(2, 3, 4)); - var serverSetPosition = new Vector3(3, 4, 5); - var serverSetScale = new Vector3(4, 5, 6); - var serverSetRotation = Quaternion.LookRotation(new Vector3(5, 6, 7)); - - testComponent.AnticipateMove(anticipePosition); - testComponent.AnticipateScale(anticipeScale); - testComponent.AnticipateRotate(anticipeRotation); - - var rpcComponent = testComponent.GetComponent(); - rpcComponent.MoveRpc(serverSetPosition); - rpcComponent.RotateRpc(serverSetRotation); - rpcComponent.ScaleRpc(serverSetScale); - - WaitForMessagesReceivedWithTimeTravel(new List - { - typeof(RpcMessage), - typeof(RpcMessage), - typeof(RpcMessage), - }, new List { m_ServerNetworkManager }); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - var percentChanged = 1f / 60f; - - AssertVectorsAreEquivalent(Vector3.Lerp(anticipePosition, serverSetPosition, percentChanged), testComponent.transform.position); - AssertVectorsAreEquivalent(Vector3.Lerp(anticipeScale, serverSetScale, percentChanged), testComponent.transform.localScale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(anticipeRotation, serverSetRotation, percentChanged), testComponent.transform.rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(anticipePosition, serverSetPosition, percentChanged), testComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(Vector3.Lerp(anticipeScale, serverSetScale, percentChanged), testComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(anticipeRotation, serverSetRotation, percentChanged), testComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, testComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, testComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, testComponent.AuthoritativeState.Rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(startPosition, serverSetPosition, percentChanged), otherClientComponent.transform.position); - AssertVectorsAreEquivalent(Vector3.Lerp(startScale, serverSetScale, percentChanged), otherClientComponent.transform.localScale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(startRotation, serverSetRotation, percentChanged), otherClientComponent.transform.rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(startPosition, serverSetPosition, percentChanged), otherClientComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(Vector3.Lerp(startScale, serverSetScale, percentChanged), otherClientComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(startRotation, serverSetRotation, percentChanged), otherClientComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, otherClientComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, otherClientComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, otherClientComponent.AuthoritativeState.Rotation); - - for (var i = 1; i < 60; ++i) - { - TimeTravel(1f / 60f, 1); - percentChanged = 1f / 60f * (i + 1); - - AssertVectorsAreEquivalent(Vector3.Lerp(anticipePosition, serverSetPosition, percentChanged), testComponent.transform.position); - AssertVectorsAreEquivalent(Vector3.Lerp(anticipeScale, serverSetScale, percentChanged), testComponent.transform.localScale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(anticipeRotation, serverSetRotation, percentChanged), testComponent.transform.rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(anticipePosition, serverSetPosition, percentChanged), testComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(Vector3.Lerp(anticipeScale, serverSetScale, percentChanged), testComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(anticipeRotation, serverSetRotation, percentChanged), testComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, testComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, testComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, testComponent.AuthoritativeState.Rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(startPosition, serverSetPosition, percentChanged), otherClientComponent.transform.position); - AssertVectorsAreEquivalent(Vector3.Lerp(startScale, serverSetScale, percentChanged), otherClientComponent.transform.localScale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(startRotation, serverSetRotation, percentChanged), otherClientComponent.transform.rotation); - - AssertVectorsAreEquivalent(Vector3.Lerp(startPosition, serverSetPosition, percentChanged), otherClientComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(Vector3.Lerp(startScale, serverSetScale, percentChanged), otherClientComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(Quaternion.Lerp(startRotation, serverSetRotation, percentChanged), otherClientComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, otherClientComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, otherClientComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, otherClientComponent.AuthoritativeState.Rotation); - } - TimeTravel(1f / 60f, 1); - - AssertVectorsAreEquivalent(serverSetPosition, testComponent.transform.position); - AssertVectorsAreEquivalent(serverSetScale, testComponent.transform.localScale); - AssertQuaternionsAreEquivalent(serverSetRotation, testComponent.transform.rotation); - - AssertVectorsAreEquivalent(serverSetPosition, testComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(serverSetScale, testComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, testComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, testComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, testComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, testComponent.AuthoritativeState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, otherClientComponent.transform.position); - AssertVectorsAreEquivalent(serverSetScale, otherClientComponent.transform.localScale); - AssertQuaternionsAreEquivalent(serverSetRotation, otherClientComponent.transform.rotation); - - AssertVectorsAreEquivalent(serverSetPosition, otherClientComponent.AnticipatedState.Position); - AssertVectorsAreEquivalent(serverSetScale, otherClientComponent.AnticipatedState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, otherClientComponent.AnticipatedState.Rotation); - - AssertVectorsAreEquivalent(serverSetPosition, otherClientComponent.AuthoritativeState.Position); - AssertVectorsAreEquivalent(serverSetScale, otherClientComponent.AuthoritativeState.Scale); - AssertQuaternionsAreEquivalent(serverSetRotation, otherClientComponent.AuthoritativeState.Rotation); - } - - [Test] - public void WhenServerChangesReanticipeValue_ValuesAreReanticiped() - { - var testComponent = GetTestComponent(); - var otherClientComponent = GetOtherClientComponent(); - - testComponent.GetComponent().ShouldMove = true; - otherClientComponent.GetComponent().ShouldMove = true; - - var serverComponent = GetServerComponent(); - serverComponent.Interpolate = false; - serverComponent.transform.position = new Vector3(0, 1, 2); - var rpcComponent = testComponent.GetComponent(); - rpcComponent.MoveRpc(new Vector3(0, 1, 2)); - - WaitForMessageReceivedWithTimeTravel(new List { m_ServerNetworkManager }); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - Assert.AreEqual(new Vector3(0, 6, 2), testComponent.transform.position); - Assert.AreEqual(new Vector3(0, 6, 2), testComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(0, 1, 2), testComponent.AuthoritativeState.Position); - - Assert.AreEqual(new Vector3(0, 6, 2), otherClientComponent.transform.position); - Assert.AreEqual(new Vector3(0, 6, 2), otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(0, 1, 2), otherClientComponent.AuthoritativeState.Position); - } - - [Test] - public void WhenStaleDataArrivesToIgnoreVariable_ItIsIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames) - { - m_ServerNetworkManager.NetworkConfig.TickRate = tickRate; - m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate; - - for (var i = 0; i < skipFrames; ++i) - { - TimeTravel(1 / 60f, 1); - } - - var serverComponent = GetServerComponent(); - serverComponent.Interpolate = false; - - var testComponent = GetTestComponent(); - testComponent.StaleDataHandling = StaleDataHandling.Ignore; - testComponent.Interpolate = false; - - var otherClientComponent = GetOtherClientComponent(); - otherClientComponent.StaleDataHandling = StaleDataHandling.Ignore; - otherClientComponent.Interpolate = false; - - var rpcComponent = testComponent.GetComponent(); - rpcComponent.MoveRpc(new Vector3(1, 2, 3)); - - WaitForMessageReceivedWithTimeTravel(new List { m_ServerNetworkManager }); - - testComponent.AnticipateMove(new Vector3(0, 5, 0)); - rpcComponent.MoveRpc(new Vector3(4, 5, 6)); - - // Depending on tick rate, one of these two things will happen. - // The assertions are different based on this... either the tick rate is slow enough that the second RPC is received - // before the next update and we move to 4, 5, 6, or the tick rate is fast enough that the next update is sent out - // before the RPC is received and we get the update for the move to 1, 2, 3. Both are valid, what we want to assert - // here is that the anticipated state never becomes 1, 2, 3. - WaitForConditionOrTimeOutWithTimeTravel(() => testComponent.AuthoritativeState.Position == new Vector3(1, 2, 3) || testComponent.AuthoritativeState.Position == new Vector3(4, 5, 6)); - - if (testComponent.AnticipatedState.Position == new Vector3(4, 5, 6)) - { - // Anticiped client received this data for a time earlier than its anticipation, and should have prioritized the anticiped value - Assert.AreEqual(new Vector3(4, 5, 6), testComponent.transform.position); - Assert.AreEqual(new Vector3(4, 5, 6), testComponent.AnticipatedState.Position); - // However, the authoritative value still gets updated - Assert.AreEqual(new Vector3(4, 5, 6), testComponent.AuthoritativeState.Position); - - // Other client got the server value and had made no anticipation, so it applies it to the anticiped value as well. - Assert.AreEqual(new Vector3(4, 5, 6), otherClientComponent.transform.position); - Assert.AreEqual(new Vector3(4, 5, 6), otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(4, 5, 6), otherClientComponent.AuthoritativeState.Position); - } - else - { - // Anticiped client received this data for a time earlier than its anticipation, and should have prioritized the anticiped value - Assert.AreEqual(new Vector3(0, 5, 0), testComponent.transform.position); - Assert.AreEqual(new Vector3(0, 5, 0), testComponent.AnticipatedState.Position); - // However, the authoritative value still gets updated - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.AuthoritativeState.Position); - - // Other client got the server value and had made no anticipation, so it applies it to the anticiped value as well. - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.transform.position); - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.AuthoritativeState.Position); - } - } - - - [Test] - public void WhenNonStaleDataArrivesToIgnoreVariable_ItIsNotIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames) - { - m_ServerNetworkManager.NetworkConfig.TickRate = tickRate; - m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate; - - for (var i = 0; i < skipFrames; ++i) - { - TimeTravel(1 / 60f, 1); - } - - var serverComponent = GetServerComponent(); - serverComponent.Interpolate = false; - - var testComponent = GetTestComponent(); - testComponent.StaleDataHandling = StaleDataHandling.Ignore; - testComponent.Interpolate = false; - - var otherClientComponent = GetOtherClientComponent(); - otherClientComponent.StaleDataHandling = StaleDataHandling.Ignore; - otherClientComponent.Interpolate = false; - - testComponent.AnticipateMove(new Vector3(0, 5, 0)); - var rpcComponent = testComponent.GetComponent(); - rpcComponent.MoveRpc(new Vector3(1, 2, 3)); - - WaitForMessageReceivedWithTimeTravel(new List { m_ServerNetworkManager }); - - WaitForConditionOrTimeOutWithTimeTravel(() => testComponent.AuthoritativeState.Position == serverComponent.transform.position && otherClientComponent.AuthoritativeState.Position == serverComponent.transform.position); - - // Anticiped client received this data for a time earlier than its anticipation, and should have prioritized the anticiped value - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.transform.position); - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.AnticipatedState.Position); - // However, the authoritative value still gets updated - Assert.AreEqual(new Vector3(1, 2, 3), testComponent.AuthoritativeState.Position); - - // Other client got the server value and had made no anticipation, so it applies it to the anticiped value as well. - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.transform.position); - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.AnticipatedState.Position); - Assert.AreEqual(new Vector3(1, 2, 3), otherClientComponent.AuthoritativeState.Position); - } - } -} diff --git a/Tests/Runtime/NetworkTransformAnticipationTests.cs.meta b/Tests/Runtime/NetworkTransformAnticipationTests.cs.meta deleted file mode 100644 index ae75b6b..0000000 --- a/Tests/Runtime/NetworkTransformAnticipationTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ceb074b080c27184a9f669cd68355955 \ No newline at end of file diff --git a/Tests/Runtime/NetworkUpdateLoopTests.cs b/Tests/Runtime/NetworkUpdateLoopTests.cs deleted file mode 100644 index 06d10d4..0000000 --- a/Tests/Runtime/NetworkUpdateLoopTests.cs +++ /dev/null @@ -1,437 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using NUnit.Framework; -using UnityEngine; -using UnityEngine.LowLevel; -using UnityEngine.PlayerLoop; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkUpdateLoopTests - { - [Test] - public void RegisterCustomLoopInTheMiddle() - { - // caching the current PlayerLoop (to prevent side-effects on other tests) - var cachedPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - { - // since current PlayerLoop already took NetworkUpdateLoop systems inside, - // we are going to swap it with the default PlayerLoop temporarily for testing - PlayerLoop.SetPlayerLoop(PlayerLoop.GetDefaultPlayerLoop()); - - NetworkUpdateLoop.RegisterLoopSystems(); - - var curPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - int initSubsystemCount = curPlayerLoop.subSystemList[0].subSystemList.Length; - var newInitSubsystems = new PlayerLoopSystem[initSubsystemCount + 1]; - Array.Copy(curPlayerLoop.subSystemList[0].subSystemList, newInitSubsystems, initSubsystemCount); - newInitSubsystems[initSubsystemCount] = new PlayerLoopSystem { type = typeof(NetworkUpdateLoopTests) }; - curPlayerLoop.subSystemList[0].subSystemList = newInitSubsystems; - PlayerLoop.SetPlayerLoop(curPlayerLoop); - - NetworkUpdateLoop.UnregisterLoopSystems(); - - // our custom `PlayerLoopSystem` with the type of `NetworkUpdateLoopTests` should still exist - Assert.AreEqual(typeof(NetworkUpdateLoopTests), PlayerLoop.GetCurrentPlayerLoop().subSystemList[0].subSystemList.Last().type); - } - // replace the current PlayerLoop with the cached PlayerLoop after the test - PlayerLoop.SetPlayerLoop(cachedPlayerLoop); - } - - [UnityTest] - public IEnumerator RegisterAndUnregisterSystems() - { - // caching the current PlayerLoop (it will have NetworkUpdateLoop systems registered) - var cachedPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - { - // since current PlayerLoop already took NetworkUpdateLoop systems inside, - // we are going to swap it with the default PlayerLoop temporarily for testing - PlayerLoop.SetPlayerLoop(PlayerLoop.GetDefaultPlayerLoop()); - - var oldPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - - NetworkUpdateLoop.RegisterLoopSystems(); - - int nextFrameNumber = Time.frameCount + 1; - yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); - - NetworkUpdateLoop.UnregisterLoopSystems(); - - var newPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - - // recursively compare old and new PlayerLoop systems and their subsystems - AssertAreEqualPlayerLoopSystems(newPlayerLoop, oldPlayerLoop); - } - // replace the current PlayerLoop with the cached PlayerLoop after the test - PlayerLoop.SetPlayerLoop(cachedPlayerLoop); - } - - private void AssertAreEqualPlayerLoopSystems(PlayerLoopSystem leftPlayerLoop, PlayerLoopSystem rightPlayerLoop) - { - Assert.AreEqual(leftPlayerLoop.type, rightPlayerLoop.type); - Assert.AreEqual(leftPlayerLoop.subSystemList?.Length ?? 0, rightPlayerLoop.subSystemList?.Length ?? 0); - for (int i = 0; i < (leftPlayerLoop.subSystemList?.Length ?? 0); i++) - { - AssertAreEqualPlayerLoopSystems(leftPlayerLoop.subSystemList[i], rightPlayerLoop.subSystemList[i]); - } - } - - [Test] - public void UpdateStageSystems() - { - var currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); - for (int i = 0; i < currentPlayerLoop.subSystemList.Length; i++) - { - var playerLoopSystem = currentPlayerLoop.subSystemList[i]; - var subsystems = playerLoopSystem.subSystemList.ToList(); - - if (playerLoopSystem.type == typeof(Initialization)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkInitialization)), - nameof(NetworkUpdateLoop.NetworkInitialization)); - } - else if (playerLoopSystem.type == typeof(EarlyUpdate)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkEarlyUpdate)), - nameof(NetworkUpdateLoop.NetworkEarlyUpdate)); - } - else if (playerLoopSystem.type == typeof(FixedUpdate)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkFixedUpdate)), - nameof(NetworkUpdateLoop.NetworkFixedUpdate)); - } - else if (playerLoopSystem.type == typeof(PreUpdate)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkPreUpdate)), - nameof(NetworkUpdateLoop.NetworkPreUpdate)); - } - else if (playerLoopSystem.type == typeof(Update)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkUpdate)), - nameof(NetworkUpdateLoop.NetworkUpdate)); - } - else if (playerLoopSystem.type == typeof(PreLateUpdate)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkPreLateUpdate)), - nameof(NetworkUpdateLoop.NetworkPreLateUpdate)); - } - else if (playerLoopSystem.type == typeof(PostLateUpdate)) - { - Assert.True( - subsystems.Exists(s => s.type == typeof(NetworkUpdateLoop.NetworkPostLateUpdate)), - nameof(NetworkUpdateLoop.NetworkPostLateUpdate)); - } - } - } - - private struct NetworkUpdateCallbacks - { - public Action OnInitialization; - public Action OnEarlyUpdate; - public Action OnFixedUpdate; - public Action OnPreUpdate; - public Action OnUpdate; - public Action OnPreLateUpdate; - public Action OnPostLateUpdate; - } - - private class MyPlainScript : IDisposable, INetworkUpdateSystem - { - public NetworkUpdateCallbacks UpdateCallbacks; - - public void Initialize() - { - this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate); - } - - public void NetworkUpdate(NetworkUpdateStage updateStage) - { - switch (updateStage) - { - case NetworkUpdateStage.Initialization: - UpdateCallbacks.OnInitialization(); - break; - case NetworkUpdateStage.EarlyUpdate: - UpdateCallbacks.OnEarlyUpdate(); - break; - case NetworkUpdateStage.FixedUpdate: - UpdateCallbacks.OnFixedUpdate(); - break; - case NetworkUpdateStage.PreUpdate: - UpdateCallbacks.OnPreUpdate(); - break; - case NetworkUpdateStage.Update: - UpdateCallbacks.OnUpdate(); - break; - case NetworkUpdateStage.PreLateUpdate: - UpdateCallbacks.OnPreLateUpdate(); - break; - case NetworkUpdateStage.PostLateUpdate: - UpdateCallbacks.OnPostLateUpdate(); - break; - } - } - - public void Dispose() - { - this.UnregisterAllNetworkUpdates(); - } - } - - [UnityTest] - public IEnumerator UpdateStagesPlain() - { - const int kNetInitializationIndex = 0; - const int kNetEarlyUpdateIndex = 1; - const int kNetFixedUpdateIndex = 2; - const int kNetPreUpdateIndex = 3; - const int kNetUpdateIndex = 4; - const int kNetPreLateUpdateIndex = 5; - const int kNetPostLateUpdateIndex = 6; - int[] netUpdates = new int[7]; - - bool isTesting = false; - using var plainScript = new MyPlainScript(); - plainScript.UpdateCallbacks = new NetworkUpdateCallbacks - { - OnInitialization = () => - { - if (isTesting) - { - netUpdates[kNetInitializationIndex]++; - } - }, - OnEarlyUpdate = () => - { - if (isTesting) - { - netUpdates[kNetEarlyUpdateIndex]++; - } - }, - OnFixedUpdate = () => - { - if (isTesting) - { - netUpdates[kNetFixedUpdateIndex]++; - } - }, - OnPreUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPreUpdateIndex]++; - } - }, - OnUpdate = () => - { - if (isTesting) - { - netUpdates[kNetUpdateIndex]++; - } - }, - OnPreLateUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPreLateUpdateIndex]++; - } - }, - OnPostLateUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPostLateUpdateIndex]++; - } - } - }; - - plainScript.Initialize(); - int nextFrameNumber = Time.frameCount + 1; - yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); - isTesting = true; - - const int kRunTotalFrames = 16; - int waitFrameNumber = Time.frameCount + kRunTotalFrames; - yield return new WaitUntil(() => Time.frameCount >= waitFrameNumber); - - Assert.AreEqual(0, netUpdates[kNetInitializationIndex]); - Assert.AreEqual(kRunTotalFrames, netUpdates[kNetEarlyUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetFixedUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetPreUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetUpdateIndex]); - Assert.AreEqual(kRunTotalFrames, netUpdates[kNetPreLateUpdateIndex]); - Assert.AreEqual(0, netUpdates[kNetPostLateUpdateIndex]); - } - - private struct MonoBehaviourCallbacks - { - public Action OnFixedUpdate; - public Action OnUpdate; - public Action OnLateUpdate; - } - - private class MyGameScript : MonoBehaviour, INetworkUpdateSystem - { - public NetworkUpdateCallbacks UpdateCallbacks; - public MonoBehaviourCallbacks BehaviourCallbacks; - - private void Awake() - { - this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate); - this.RegisterNetworkUpdate(NetworkUpdateStage.PostLateUpdate); - - // intentionally try to register for 'PreUpdate' stage twice - // it should be ignored and the instance should not be registered twice - // otherwise test would fail because it would call 'OnPreUpdate()' twice - // which would ultimately increment 'netUpdates[idx]' integer twice - // and cause 'Assert.AreEqual()' to fail the test - this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate); - } - - public void NetworkUpdate(NetworkUpdateStage updateStage) - { - switch (updateStage) - { - case NetworkUpdateStage.FixedUpdate: - UpdateCallbacks.OnFixedUpdate(); - break; - case NetworkUpdateStage.PreUpdate: - UpdateCallbacks.OnPreUpdate(); - break; - case NetworkUpdateStage.PreLateUpdate: - UpdateCallbacks.OnPreLateUpdate(); - break; - case NetworkUpdateStage.PostLateUpdate: - UpdateCallbacks.OnPostLateUpdate(); - break; - } - } - - private void FixedUpdate() - { - BehaviourCallbacks.OnFixedUpdate(); - } - - private void Update() - { - BehaviourCallbacks.OnUpdate(); - } - - private void LateUpdate() - { - BehaviourCallbacks.OnLateUpdate(); - } - - private void OnDestroy() - { - this.UnregisterAllNetworkUpdates(); - } - } - - [UnityTest] - public IEnumerator UpdateStagesMixed() - { - const int kNetFixedUpdateIndex = 0; - const int kNetPreUpdateIndex = 1; - const int kNetPreLateUpdateIndex = 2; - const int kNetPostLateUpdateIndex = 3; - int[] netUpdates = new int[4]; - const int kMonoFixedUpdateIndex = 0; - const int kMonoUpdateIndex = 1; - const int kMonoLateUpdateIndex = 2; - int[] monoUpdates = new int[3]; - - bool isTesting = false; - { - var gameObject = new GameObject($"{nameof(NetworkUpdateLoopTests)}.{nameof(UpdateStagesMixed)} (Dummy)"); - var gameScript = gameObject.AddComponent(); - gameScript.UpdateCallbacks = new NetworkUpdateCallbacks - { - OnFixedUpdate = () => - { - if (isTesting) - { - netUpdates[kNetFixedUpdateIndex]++; - Assert.AreEqual(monoUpdates[kMonoFixedUpdateIndex] + 1, netUpdates[kNetFixedUpdateIndex]); - } - }, - OnPreUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPreUpdateIndex]++; - Assert.AreEqual(monoUpdates[kMonoUpdateIndex] + 1, netUpdates[kNetPreUpdateIndex]); - } - }, - OnPreLateUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPreLateUpdateIndex]++; - Assert.AreEqual(monoUpdates[kMonoLateUpdateIndex] + 1, netUpdates[kNetPreLateUpdateIndex]); - } - }, - OnPostLateUpdate = () => - { - if (isTesting) - { - netUpdates[kNetPostLateUpdateIndex]++; - Assert.AreEqual(netUpdates[kNetPostLateUpdateIndex], netUpdates[kNetPreLateUpdateIndex]); - } - } - }; - gameScript.BehaviourCallbacks = new MonoBehaviourCallbacks - { - OnFixedUpdate = () => - { - if (isTesting) - { - monoUpdates[kMonoFixedUpdateIndex]++; - Assert.AreEqual(netUpdates[kNetFixedUpdateIndex], monoUpdates[kMonoFixedUpdateIndex]); - } - }, - OnUpdate = () => - { - if (isTesting) - { - monoUpdates[kMonoUpdateIndex]++; - Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); - } - }, - OnLateUpdate = () => - { - if (isTesting) - { - monoUpdates[kMonoLateUpdateIndex]++; - Assert.AreEqual(netUpdates[kNetPreLateUpdateIndex], monoUpdates[kMonoLateUpdateIndex]); - } - } - }; - - int nextFrameNumber = Time.frameCount + 1; - yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); - isTesting = true; - - const int kRunTotalFrames = 16; - int waitFrameNumber = Time.frameCount + kRunTotalFrames; - yield return new WaitUntil(() => Time.frameCount >= waitFrameNumber); - - Assert.AreEqual(kRunTotalFrames, netUpdates[kNetPreUpdateIndex]); - Assert.AreEqual(netUpdates[kNetPreUpdateIndex], monoUpdates[kMonoUpdateIndex]); - - UnityEngine.Object.DestroyImmediate(gameObject); - } - } - } -} diff --git a/Tests/Runtime/NetworkUpdateLoopTests.cs.meta b/Tests/Runtime/NetworkUpdateLoopTests.cs.meta deleted file mode 100644 index 849c0f4..0000000 --- a/Tests/Runtime/NetworkUpdateLoopTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ffdb76de4852b3447b8cd673f0ca3ade -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkVariable.meta b/Tests/Runtime/NetworkVariable.meta deleted file mode 100644 index 8dbf0bc..0000000 --- a/Tests/Runtime/NetworkVariable.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7b4da27c6efa9684893f85f5d3ad80e6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs b/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs deleted file mode 100644 index 892e70d..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - internal class NetworkVarBufferCopyTest : NetcodeIntegrationTest - { - internal class DummyNetVar : NetworkVariableBase - { - private const int k_DummyValue = 0x13579BDF; - public bool DeltaWritten; - public bool FieldWritten; - public bool DeltaRead; - public bool FieldRead; - - public override void WriteDelta(FastBufferWriter writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(k_DummyValue) + 1); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(1, 1); - } - writer.WriteValue(k_DummyValue); - - DeltaWritten = true; - } - - public override void WriteField(FastBufferWriter writer) - { - writer.TryBeginWrite(FastBufferWriter.GetWriteSize(k_DummyValue) + 1); - using (var bitWriter = writer.EnterBitwiseContext()) - { - bitWriter.WriteBits(1, 1); - } - writer.WriteValue(k_DummyValue); - - FieldWritten = true; - } - - public override void ReadField(FastBufferReader reader) - { - reader.TryBeginRead(FastBufferWriter.GetWriteSize(k_DummyValue) + 1); - using (var bitReader = reader.EnterBitwiseContext()) - { - bitReader.ReadBits(out byte b, 1); - } - - reader.ReadValue(out int i); - Assert.AreEqual(k_DummyValue, i); - - FieldRead = true; - } - - public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) - { - reader.TryBeginRead(FastBufferWriter.GetWriteSize(k_DummyValue) + 1); - using (var bitReader = reader.EnterBitwiseContext()) - { - bitReader.ReadBits(out byte b, 1); - } - - reader.ReadValue(out int i); - Assert.AreEqual(k_DummyValue, i); - - DeltaRead = true; - } - - public DummyNetVar( - NetworkVariableReadPermission readPerm = DefaultReadPerm, - NetworkVariableWritePermission writePerm = DefaultWritePerm) : base(readPerm, writePerm) { } - } - - internal class DummyNetBehaviour : NetworkBehaviour - { - public static bool DistributedAuthority; - public DummyNetVar NetVar; - - private void Awake() - { - if (DistributedAuthority) - { - NetVar = new DummyNetVar(writePerm: NetworkVariableWritePermission.Owner); - } - else - { - NetVar = new DummyNetVar(); - } - } - - public override void OnNetworkSpawn() - { - if ((NetworkManager.DistributedAuthorityMode && !IsOwner) || (!NetworkManager.DistributedAuthorityMode && !IsServer)) - { - ClientDummyNetBehaviourSpawned(this); - } - base.OnNetworkSpawn(); - } - } - protected override int NumberOfClients => 1; - - public NetworkVarBufferCopyTest(HostOrServer hostOrServer) : base(hostOrServer) { } - - private static List s_ClientDummyNetBehavioursSpawned = new List(); - public static void ClientDummyNetBehaviourSpawned(DummyNetBehaviour dummyNetBehaviour) - { - s_ClientDummyNetBehavioursSpawned.Add(dummyNetBehaviour); - } - - protected override IEnumerator OnSetup() - { - s_ClientDummyNetBehavioursSpawned.Clear(); - return base.OnSetup(); - } - - protected override void OnCreatePlayerPrefab() - { - DummyNetBehaviour.DistributedAuthority = m_DistributedAuthority; - m_PlayerPrefab.AddComponent(); - } - - [UnityTest] - public IEnumerator TestEntireBufferIsCopiedOnNetworkVariableDelta() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ServerNetworkManager, serverClientPlayerResult); - - var serverSideClientPlayer = serverClientPlayerResult.Result; - var serverComponent = serverSideClientPlayer.GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ClientNetworkManagers[0], clientClientPlayerResult); - - var clientSideClientPlayer = clientClientPlayerResult.Result; - var clientComponent = clientSideClientPlayer.GetComponent(); - - // Wait for the DummyNetBehaviours on the client side to notify they have been initialized and spawned - yield return WaitForConditionOrTimeOut(() => s_ClientDummyNetBehavioursSpawned.Count >= 1); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client side DummyNetBehaviour to register it was spawned!"); - - // Check that FieldWritten is written when dirty - var authorityComponent = m_DistributedAuthority ? clientComponent : serverComponent; - var nonAuthorityComponent = m_DistributedAuthority ? serverComponent : clientComponent; - authorityComponent.NetVar.SetDirty(true); - yield return s_DefaultWaitForTick; - Assert.True(authorityComponent.NetVar.FieldWritten); - // Check that DeltaWritten is written when dirty - authorityComponent.NetVar.SetDirty(true); - yield return s_DefaultWaitForTick; - Assert.True(authorityComponent.NetVar.DeltaWritten); - - - // Check that both FieldRead and DeltaRead were invoked on the client side - yield return WaitForConditionOrTimeOut(() => nonAuthorityComponent.NetVar.FieldRead == true && nonAuthorityComponent.NetVar.DeltaRead == true); - - var timedOutMessage = "Timed out waiting for client reads: "; - if (s_GlobalTimeoutHelper.TimedOut) - { - if (!nonAuthorityComponent.NetVar.FieldRead) - { - timedOutMessage += "[FieldRead]"; - } - - if (!nonAuthorityComponent.NetVar.DeltaRead) - { - timedOutMessage += "[DeltaRead]"; - } - } - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, timedOutMessage); - } - } -} diff --git a/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs.meta deleted file mode 100644 index 88e49e3..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVarBufferCopyTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a7d44caa76a64b02978f5aca0e7b576a -timeCreated: 1627926008 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs deleted file mode 100644 index c436275..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs +++ /dev/null @@ -1,420 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkVariableAnticipationComponent : NetworkBehaviour - { - public AnticipatedNetworkVariable SnapOnAnticipationFailVariable = new AnticipatedNetworkVariable(0, StaleDataHandling.Ignore); - public AnticipatedNetworkVariable SmoothOnAnticipationFailVariable = new AnticipatedNetworkVariable(0, StaleDataHandling.Reanticipate); - public AnticipatedNetworkVariable ReanticipateOnAnticipationFailVariable = new AnticipatedNetworkVariable(0, StaleDataHandling.Reanticipate); - - public override void OnReanticipate(double lastRoundTripTime) - { - if (SmoothOnAnticipationFailVariable.ShouldReanticipate) - { - if (Mathf.Abs(SmoothOnAnticipationFailVariable.AuthoritativeValue - SmoothOnAnticipationFailVariable.PreviousAnticipatedValue) > Mathf.Epsilon) - { - SmoothOnAnticipationFailVariable.Smooth(SmoothOnAnticipationFailVariable.PreviousAnticipatedValue, SmoothOnAnticipationFailVariable.AuthoritativeValue, 1, Mathf.Lerp); - } - } - - if (ReanticipateOnAnticipationFailVariable.ShouldReanticipate) - { - // Would love to test some stuff about anticipation based on time, but that is difficult to test accurately. - // This reanticipating variable will just always anticipate a value 5 higher than the server value. - ReanticipateOnAnticipationFailVariable.Anticipate(ReanticipateOnAnticipationFailVariable.AuthoritativeValue + 5); - } - } - - public bool SnapRpcResponseReceived = false; - - [Rpc(SendTo.Server)] - public void SetSnapValueRpc(int i, RpcParams rpcParams = default) - { - SnapOnAnticipationFailVariable.AuthoritativeValue = i; - SetSnapValueResponseRpc(RpcTarget.Single(rpcParams.Receive.SenderClientId, RpcTargetUse.Temp)); - } - - [Rpc(SendTo.SpecifiedInParams)] - public void SetSnapValueResponseRpc(RpcParams rpcParams) - { - SnapRpcResponseReceived = true; - } - - [Rpc(SendTo.Server)] - public void SetSmoothValueRpc(float f) - { - SmoothOnAnticipationFailVariable.AuthoritativeValue = f; - } - - [Rpc(SendTo.Server)] - public void SetReanticipateValueRpc(float f) - { - ReanticipateOnAnticipationFailVariable.AuthoritativeValue = f; - } - } - - internal class NetworkVariableAnticipationTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected override void OnPlayerPrefabGameObjectCreated() - { - m_PlayerPrefab.AddComponent(); - } - - public NetworkVariableAnticipationComponent GetTestComponent() - { - return m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - } - - public NetworkVariableAnticipationComponent GetServerComponent() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.NetworkManager == m_ServerNetworkManager && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId) - { - return obj; - } - } - - return null; - } - - public NetworkVariableAnticipationComponent GetOtherClientComponent() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.NetworkManager == m_ClientNetworkManagers[1] && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId) - { - return obj; - } - } - - return null; - } - - [Test] - public void WhenAnticipating_ValueChangesImmediately() - { - var testComponent = GetTestComponent(); - - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - testComponent.SmoothOnAnticipationFailVariable.Anticipate(15); - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20); - - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(15, testComponent.SmoothOnAnticipationFailVariable.Value); - Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.Value); - } - - [Test] - public void WhenAnticipating_AuthoritativeValueDoesNotChange() - { - var testComponent = GetTestComponent(); - - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - testComponent.SmoothOnAnticipationFailVariable.Anticipate(15); - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20); - - Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - } - - [Test] - public void WhenAnticipating_ServerDoesNotChange() - { - var testComponent = GetTestComponent(); - - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - testComponent.SmoothOnAnticipationFailVariable.Anticipate(15); - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20); - - var serverComponent = GetServerComponent(); - - Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.Value); - Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.Value); - - TimeTravel(2, 120); - - Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, serverComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, serverComponent.SmoothOnAnticipationFailVariable.Value); - Assert.AreEqual(0, serverComponent.ReanticipateOnAnticipationFailVariable.Value); - } - - [Test] - public void WhenAnticipating_OtherClientDoesNotChange() - { - var testComponent = GetTestComponent(); - - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - testComponent.SmoothOnAnticipationFailVariable.Anticipate(15); - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(20); - - var otherClientComponent = GetOtherClientComponent(); - - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value); - - TimeTravel(2, 120); - - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value); - } - - [Test] - public void WhenServerChangesSnapValue_ValuesAreUpdated() - { - var testComponent = GetTestComponent(); - - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - testComponent.SetSnapValueRpc(10); - - WaitForMessageReceivedWithTimeTravel( - new List { m_ServerNetworkManager } - ); - - var serverComponent = GetServerComponent(); - Assert.AreEqual(10, serverComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(10, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - Assert.AreEqual(10, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(10, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - } - - [Test] - public void WhenServerChangesSmoothValue_ValuesAreLerped() - { - var testComponent = GetTestComponent(); - - testComponent.SmoothOnAnticipationFailVariable.Anticipate(15); - - Assert.AreEqual(15, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(0, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - // Set to a different value to simulate a anticipation failure - will lerp between the anticipated value - // and the actual one - testComponent.SetSmoothValueRpc(20); - - WaitForMessageReceivedWithTimeTravel( - new List { m_ServerNetworkManager } - ); - - var serverComponent = GetServerComponent(); - Assert.AreEqual(20, serverComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, serverComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(0, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - Assert.AreEqual(15 + 1f / 60f * 5, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - Assert.AreEqual(0 + 1f / 60f * 20, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - for (var i = 1; i < 60; ++i) - { - TimeTravel(1f / 60f, 1); - - Assert.AreEqual(15 + 1f / 60f * 5 * (i + 1), testComponent.SmoothOnAnticipationFailVariable.Value, 0.00001); - Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - Assert.AreEqual(0 + 1f / 60f * 20 * (i + 1), otherClientComponent.SmoothOnAnticipationFailVariable.Value, 0.00001); - Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - } - TimeTravel(1f / 60f, 1); - Assert.AreEqual(20, testComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, otherClientComponent.SmoothOnAnticipationFailVariable.Value, Mathf.Epsilon); - } - - [Test] - public void WhenServerChangesReanticipateValue_ValuesAreReanticipated() - { - var testComponent = GetTestComponent(); - - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(15); - - Assert.AreEqual(15, testComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - // Set to a different value to simulate a anticipation failure - will lerp between the anticipated value - // and the actual one - testComponent.SetReanticipateValueRpc(20); - - WaitForMessageReceivedWithTimeTravel( - new List { m_ServerNetworkManager } - ); - - var serverComponent = GetServerComponent(); - Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(0, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - Assert.AreEqual(25, testComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - - Assert.AreEqual(25, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value, Mathf.Epsilon); - Assert.AreEqual(20, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue, Mathf.Epsilon); - } - - [Test] - public void WhenNonStaleDataArrivesToIgnoreVariable_ItIsNotIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames) - { - m_ServerNetworkManager.NetworkConfig.TickRate = tickRate; - m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate; - - for (var i = 0; i < skipFrames; ++i) - { - TimeTravel(1 / 60f, 1); - } - var testComponent = GetTestComponent(); - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - testComponent.SetSnapValueRpc(20); - WaitForMessageReceivedWithTimeTravel(new List { m_ServerNetworkManager }); - - var serverComponent = GetServerComponent(); - - Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - // Both values get updated - Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - // Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well. - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - } - - [Test] - public void WhenStaleDataArrivesToIgnoreVariable_ItIsIgnored([Values(10u, 30u, 60u)] uint tickRate, [Values(0u, 1u, 2u)] uint skipFrames) - { - m_ServerNetworkManager.NetworkConfig.TickRate = tickRate; - m_ServerNetworkManager.NetworkTickSystem.TickRate = tickRate; - - for (var i = 0; i < skipFrames; ++i) - { - TimeTravel(1 / 60f, 1); - } - var testComponent = GetTestComponent(); - testComponent.SnapOnAnticipationFailVariable.Anticipate(10); - - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(0, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - testComponent.SetSnapValueRpc(30); - - var serverComponent = GetServerComponent(); - serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue = 20; - - Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(20, serverComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - if (testComponent.SnapRpcResponseReceived) - { - // In this case the tick rate is slow enough that the RPC was received and processed, so we check that. - Assert.AreEqual(30, testComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(30, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(30, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(30, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - } - else - { - // In this case, we got an update before the RPC was processed, so we should have ignored it. - // Anticipated client received this data for a tick earlier than its anticipation, and should have prioritized the anticipated value - Assert.AreEqual(10, testComponent.SnapOnAnticipationFailVariable.Value); - // However, the authoritative value still gets updated - Assert.AreEqual(20, testComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - - // Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well. - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.Value); - Assert.AreEqual(20, otherClientComponent.SnapOnAnticipationFailVariable.AuthoritativeValue); - } - } - - [Test] - public void WhenStaleDataArrivesToReanticipatedVariable_ItIsAppliedAndReanticipated() - { - var testComponent = GetTestComponent(); - testComponent.ReanticipateOnAnticipationFailVariable.Anticipate(10); - - Assert.AreEqual(10, testComponent.ReanticipateOnAnticipationFailVariable.Value); - Assert.AreEqual(0, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - - var serverComponent = GetServerComponent(); - serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue = 20; - - Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.Value); - Assert.AreEqual(20, serverComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - - Assert.AreEqual(25, testComponent.ReanticipateOnAnticipationFailVariable.Value); - // However, the authoritative value still gets updated - Assert.AreEqual(20, testComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - - // Other client got the server value and had made no anticipation, so it applies it to the anticipated value as well. - var otherClientComponent = GetOtherClientComponent(); - Assert.AreEqual(25, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value); - Assert.AreEqual(20, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue); - } - } -} diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs.meta deleted file mode 100644 index 357da56..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 74e627a9d18dcd04e9c56ab2539a6593 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs deleted file mode 100644 index 0c8a2ff..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs +++ /dev/null @@ -1,3884 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Client-Server only test - /// Validates using managed collections with NetworkVariable. - /// Managed Collections Tested: - /// - List - /// - Dictionary - /// - HashSet - /// This also does some testing on nested collections, but does - /// not test every possible combination. - /// - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - public class NetworkVariableCollectionsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private bool m_EnableDebug; - - public NetworkVariableCollectionsTests(HostOrServer hostOrServer) : base(hostOrServer) - { - m_EnableDebug = false; - } - - protected override bool OnSetVerboseDebug() - { - return m_EnableDebug; - } - - protected override IEnumerator OnSetup() - { - ListTestHelperInt.ResetState(); - ListTestHelperListInt.ResetState(); - ListTestHelperSerializableObject.ResetState(); - ListTestHelperListSerializableObject.ResetState(); - DictionaryTestHelper.ResetState(); - NestedDictionaryTestHelper.ResetState(); - HashSetBaseTypeTestHelper.ResetState(); - return base.OnSetup(); - } - - private void AddPlayerComponent() where T : ListTestHelperBase - { - var component = m_PlayerPrefab.AddComponent(); - component.SetDebugMode(m_EnableDebug); - } - - protected override void OnCreatePlayerPrefab() - { - AddPlayerComponent(); - AddPlayerComponent(); - AddPlayerComponent(); - AddPlayerComponent(); - AddPlayerComponent(); - AddPlayerComponent(); - AddPlayerComponent(); - base.OnCreatePlayerPrefab(); - } - - private List GetRandomIntList(int count) - { - var list = new List(); - for (int i = 0; i < count; i++) - { - list.Add(Random.Range(int.MinValue, int.MaxValue)); - } - return list; - } - - [UnityTest] - public IEnumerator TestListBuiltInTypeCollections() - { - var compInt = (ListTestHelperInt)null; - var compListInt = (ListTestHelperListInt)null; - var compIntServer = (ListTestHelperInt)null; - var compListIntServer = (ListTestHelperListInt)null; - - var clientList = m_ClientNetworkManagers.ToList(); - if (m_ServerNetworkManager.IsHost) - { - clientList.Insert(0, m_ServerNetworkManager); - } - - foreach (var client in clientList) - { - /////////////////////////////////////////////////////////////////////////// - // List Single dimension list - - compInt = client.LocalClient.PlayerObject.GetComponent(); - compIntServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compIntServer.name} component match!"); - var randomInt = Random.Range(int.MinValue, int.MaxValue); - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - ////////////////////////////////// - // No Write Owner Add Int - compIntServer.Add(randomInt, ListTestHelperBase.Targets.Owner); - } - - ////////////////////////////////// - // Owner Add int - compInt.Add(randomInt, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - ////////////////////////////////// - // No Write Server Add Int - compInt.Add(randomInt, ListTestHelperBase.Targets.Server); - } - - ////////////////////////////////// - // Server Add int - compIntServer.Add(randomInt, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - ////////////////////////////////// - // Owner Remove int - var index = Random.Range(0, compInt.ListCollectionOwner.Value.Count - 1); - var valueIntRemove = compInt.ListCollectionOwner.Value[index]; - compInt.Remove(valueIntRemove, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - ////////////////////////////////// - // Server Remove int - compIntServer.Remove(valueIntRemove, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compIntServer.name} component match!"); - - //////////////////////////////////// - // Owner Change int - var valueIntChange = Random.Range(int.MinValue, int.MaxValue); - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // No Write Server Change int with IsDirty restore - compIntServer.ListCollectionOwner.Value[index] = valueIntChange; - compIntServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server change failed to restore on {nameof(ListTestHelperInt)} {compInt.name}!"); - - // No Write Server Change int with owner state update override - compIntServer.ListCollectionOwner.Value[index] = valueIntChange; - } - compInt.ListCollectionOwner.Value[index] = valueIntChange; - compInt.ListCollectionOwner.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - - ////////////////////////////////// - // Server Change int - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // No Write Client Change int with IsDirty restore - compInt.ListCollectionServer.Value[index] = valueIntChange; - compInt.ListCollectionServer.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to restore on {nameof(ListTestHelperInt)} {compInt.name}!"); - - // No Write Client Change int with owner state update override - compInt.ListCollectionServer.Value[index] = valueIntChange; - } - compIntServer.ListCollectionServer.Value[index] = valueIntChange; - compIntServer.ListCollectionServer.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - //////////////////////////////////// - // Owner Add Range - compInt.AddRange(GetRandomIntList(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add range failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - ////////////////////////////////// - // Server Add Range - compIntServer.AddRange(GetRandomIntList(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add range failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compIntServer.name} component match!"); - - //////////////////////////////////// - // Owner Full Set - compInt.FullSet(GetRandomIntList(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - ////////////////////////////////// - // Server Full Set - compIntServer.FullSet(GetRandomIntList(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - //////////////////////////////////// - // Owner Clear - compInt.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {nameof(ListTestHelperInt)} {compInt.name}!"); - ////////////////////////////////// - // Server Clear - compIntServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {nameof(ListTestHelperInt)} {compIntServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compIntServer.name} component match!"); - - /////////////////////////////////////////////////////////////////////////// - // List> Nested List Validation - compListInt = client.LocalClient.PlayerObject.GetComponent(); - compListIntServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compListInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListInt.name} component match! {compListInt.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListIntServer.name} component match! {compListIntServer.GetLog()}"); - - ////////////////////////////////// - // Owner Add List item - compListInt.Add(GetRandomIntList(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - ////////////////////////////////// - // Server Add List item - compListIntServer.Add(GetRandomIntList(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - ////////////////////////////////// - // Owner Remove List item - index = Random.Range(0, compListInt.ListCollectionOwner.Value.Count - 1); - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - compListIntServer.ListCollectionOwner.Value.Remove(compListIntServer.ListCollectionOwner.Value[index]); - compListIntServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server remove failed to restore on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - // No Write Server Remove List item with update restore - compListIntServer.ListCollectionOwner.Value.Remove(compListIntServer.ListCollectionOwner.Value[index]); - } - compListInt.Remove(compListInt.ListCollectionOwner.Value[index], ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - - ////////////////////////////////// - // Server Remove List item - index = Random.Range(0, compListIntServer.ListCollectionServer.Value.Count - 1); - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // No Write Client Remove List item with CheckDirtyState restore - compListInt.Remove(compListInt.ListCollectionServer.Value[index], ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to restore on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - // No Write Client Remove List item with update restore - compListInt.Remove(compListInt.ListCollectionServer.Value[index], ListTestHelperBase.Targets.Server); - } - compListIntServer.Remove(compListIntServer.ListCollectionServer.Value[index], ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - - yield return WaitForConditionOrTimeOut(() => compListInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListInt.name} component match! {compListInt.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListIntServer.name} component match! {compListIntServer.GetLog()}"); - - //////////////////////////////////// - // Owner Change List item - index = Random.Range(0, compListInt.ListCollectionOwner.Value.Count - 1); - compListInt.ListCollectionOwner.Value[index] = GetRandomIntList(5); - compListInt.ListCollectionOwner.CheckDirtyState(); - Assert.True(compListInt.ListCollectionOwner.IsDirty(), "Client Should be dirty!"); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change index ({index}) failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - - ////////////////////////////////// - // Server Change List item - index = Random.Range(0, compListIntServer.ListCollectionServer.Value.Count - 1); - compListIntServer.ListCollectionServer.Value[index] = GetRandomIntList(5); - compListIntServer.ListCollectionServer.CheckDirtyState(); - Assert.True(compListIntServer.ListCollectionServer.IsDirty(), "Server Should be dirty!"); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - //////////////////////////////////// - // Owner Add Range of List items - var randomintListOfList = new List>(); - for (int i = 0; i < 5; i++) - { - randomintListOfList.Add(GetRandomIntList(5)); - } - compListInt.AddRange(randomintListOfList, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add range failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - ////////////////////////////////// - // Server Add Range of List items - randomintListOfList = new List>(); - for (int i = 0; i < 5; i++) - { - randomintListOfList.Add(GetRandomIntList(5)); - } - compListIntServer.AddRange(randomintListOfList, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add range failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compListIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListIntServer.name} component match!"); - - //////////////////////////////////// - // Owner Full Set List> - randomintListOfList = new List>(); - for (int i = 0; i < 5; i++) - { - randomintListOfList.Add(GetRandomIntList(5)); - } - compListInt.FullSet(randomintListOfList, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - ////////////////////////////////// - // Server Full Set List> - randomintListOfList = new List>(); - for (int i = 0; i < 5; i++) - { - randomintListOfList.Add(GetRandomIntList(5)); - } - compListIntServer.FullSet(randomintListOfList, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - //////////////////////////////////// - // Owner Clear List> - compListInt.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListInt.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {nameof(ListTestHelperListInt)} {compListInt.name}! {compListInt.GetLog()}"); - ////////////////////////////////// - // Server Clear List> - compListIntServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListIntServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {nameof(ListTestHelperListInt)} {compListIntServer.name}! {compListIntServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListInt.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListInt.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListInt.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compListIntServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListIntServer.OwnerClientId}'s {nameof(ListTestHelperInt)} {compListIntServer.name} component match!"); - } - } - - [UnityTest] - public IEnumerator TestListSerializableObjectCollections() - { - var compObject = (ListTestHelperSerializableObject)null; - var compObjectServer = (ListTestHelperSerializableObject)null; - var compListObject = (ListTestHelperListSerializableObject)null; - var compListObjectServer = (ListTestHelperListSerializableObject)null; - - var clientList = m_ClientNetworkManagers.ToList(); - if (m_ServerNetworkManager.IsHost) - { - clientList.Insert(0, m_ServerNetworkManager); - } - - foreach (var client in clientList) - { - /////////////////////////////////////////////////////////////////////////// - // List Single dimension list - compObject = client.LocalClient.PlayerObject.GetComponent(); - compObjectServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compObject.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compObjectServer.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObjectServer.name} component match!"); - - ////////////////////////////////// - // Owner Add SerializableObject - compObject.Add(SerializableObject.GetRandomObject(), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Add SerializableObject - compObjectServer.Add(SerializableObject.GetRandomObject(), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - ////////////////////////////////// - // Owner Remove SerializableObject - var index = Random.Range(0, compObject.ListCollectionOwner.Value.Count - 1); - var valueIntRemove = compObject.ListCollectionOwner.Value[index]; - compObject.Remove(valueIntRemove, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Remove SerializableObject - compObjectServer.Remove(valueIntRemove, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compObject.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compObjectServer.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObjectServer.name} component match!"); - - //////////////////////////////////// - // Owner Change SerializableObject - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // No Write Server Remove Serializable item with IsDirty restore - compObjectServer.ListCollectionOwner.Value[index] = SerializableObject.GetRandomObject(); - compObjectServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server change failed to restore on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - // No Write Server Remove Serializable item with owner state update restore - compObjectServer.ListCollectionOwner.Value[index] = SerializableObject.GetRandomObject(); - } - compObject.ListCollectionOwner.Value[index] = SerializableObject.GetRandomObject(); - compObject.ListCollectionOwner.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Change SerializableObject - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // No Write Client Remove Serializable item with IsDirty restore - compObject.ListCollectionServer.Value[index] = SerializableObject.GetRandomObject(); - compObject.ListCollectionServer.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to restore on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - // No Write Client Remove Serializable item with owner state update restore - compObject.ListCollectionServer.Value[index] = SerializableObject.GetRandomObject(); - } - compObjectServer.ListCollectionServer.Value[index] = SerializableObject.GetRandomObject(); - compObjectServer.ListCollectionServer.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - //////////////////////////////////// - // Owner Add Range SerializableObjects - compObject.AddRange(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add range failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Add Range SerializableObjects - compObjectServer.AddRange(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add range failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compObject.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compObjectServer.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObjectServer.name} component match!"); - - //////////////////////////////////// - // Owner Full Set SerializableObjects - compObject.FullSet(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Full Set SerializableObjects - compObjectServer.FullSet(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - //////////////////////////////////// - // Owner Clear - compObject.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObject.name}!"); - ////////////////////////////////// - // Server Clear - compObjectServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {nameof(ListTestHelperSerializableObject)} {compObjectServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compObject.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compObjectServer.OwnerClientId}'s {nameof(ListTestHelperSerializableObject)} {compObjectServer.name} component match!"); - - /////////////////////////////////////////////////////////////////////////// - // List> Nested List Validation - compListObject = client.LocalClient.PlayerObject.GetComponent(); - compListObjectServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compListObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListObject.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObject.name} component match! {compListObject.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListObjectServer.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name} component match! {compListObjectServer.GetLog()}"); - - ////////////////////////////////// - // Owner Add List item - compListObject.Add(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}! {compListObject.GetLog()}"); - ////////////////////////////////// - // Server Add List item - compListObjectServer.Add(SerializableObject.GetListOfRandomObjects(5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}! {compListObjectServer.GetLog()}"); - - ////////////////////////////////// - // Owner Remove List item - index = Random.Range(0, compListObject.ListCollectionOwner.Value.Count - 1); - compListObject.Remove(compListObject.ListCollectionOwner.Value[index], ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}! {compListObject.GetLog()}"); - ////////////////////////////////// - // Server Remove List item - index = Random.Range(0, compListObjectServer.ListCollectionServer.Value.Count - 1); - compListObjectServer.Remove(compListObjectServer.ListCollectionServer.Value[index], ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}! {compListObjectServer.GetLog()}"); - - - yield return WaitForConditionOrTimeOut(() => compListObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListObject.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObject.name} component match! {compListObject.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListObjectServer.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name} component match! {compListObjectServer.GetLog()}"); - - //////////////////////////////////// - // Owner Change List item - index = Random.Range(0, compListObject.ListCollectionOwner.Value.Count - 1); - compListObject.ListCollectionOwner.Value[index] = SerializableObject.GetListOfRandomObjects(5); - compListObject.ListCollectionOwner.CheckDirtyState(); - Assert.True(compListObject.ListCollectionOwner.IsDirty(), "Client Should be dirty!"); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change index ({index}) failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}! {compListObject.GetLog()}"); - - ////////////////////////////////// - // Server Change List item - index = Random.Range(0, compListObjectServer.ListCollectionServer.Value.Count - 1); - compListObjectServer.ListCollectionServer.Value[index] = SerializableObject.GetListOfRandomObjects(5); - compListObjectServer.ListCollectionServer.CheckDirtyState(); - Assert.True(compListObjectServer.ListCollectionServer.IsDirty(), "Server Should be dirty!"); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}! {compListObjectServer.GetLog()}"); - - //////////////////////////////////// - // Owner Add Range of List items - compListObject.AddRange(SerializableObject.GetListOfListOfRandomObjects(5, 5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add range failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}! {compListObject.GetLog()}"); - ////////////////////////////////// - // Server Add Range of List items - compListObjectServer.AddRange(SerializableObject.GetListOfListOfRandomObjects(5, 5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add range failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}! {compListObjectServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compListObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListObject.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compListObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListObjectServer.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name} component match!"); - - //////////////////////////////////// - // Owner Full Set List> - compListObject.FullSet(SerializableObject.GetListOfListOfRandomObjects(5, 5), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}!"); - ////////////////////////////////// - // Server Full Set List> - compListObjectServer.FullSet(SerializableObject.GetListOfListOfRandomObjects(5, 5), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}!"); - - //////////////////////////////////// - // Owner Clear List> - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Server Clear List> with IsDirty restore - compListObjectServer.ListCollectionOwner.Value.Clear(); - compListObjectServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server clear owner collection failed to restore back to last known valid state on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}!"); - // Server Clear List> with update state restore - compListObjectServer.ListCollectionOwner.Value.Clear(); - } - compListObject.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}!"); - ////////////////////////////////// - // Server Clear List> - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Client Clear List> with IsDirty restore - compListObject.ListCollectionServer.Value.Clear(); - compListObject.ListCollectionServer.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compListObject.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client clear owner collection failed to restore back to last known valid state on {nameof(ListTestHelperListSerializableObject)} {compListObject.name}!"); - - // Client Clear List> with update state restore - compListObject.ListCollectionServer.Value.Clear(); - } - compListObjectServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compListObjectServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name}!"); - - yield return WaitForConditionOrTimeOut(() => compListObject.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compListObject.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObject.name} component match!"); - - yield return WaitForConditionOrTimeOut(() => compListObjectServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compListObjectServer.OwnerClientId}'s {nameof(ListTestHelperListSerializableObject)} {compListObjectServer.name} component match!"); - } - } - - private int m_CurrentKey; - private int GetNextKey() - { - m_CurrentKey++; - return m_CurrentKey; - } - - private int m_Stage; - - private List m_Clients; - - private bool m_IsInitialized = false; - private StringBuilder m_InitializedStatus = new StringBuilder(); - - private IEnumerator ValidateClients(NetworkManager clientBeingTested, bool initialize = false) - { - VerboseDebug($">>>>>>>>>>>>>>>>>>>>>>>>>[Client-{clientBeingTested.LocalClientId}][{m_Stage}][Validation]<<<<<<<<<<<<<<<<<<<<<<<<< "); - m_Stage++; - var compDictionary = (DictionaryTestHelper)null; - var compDictionaryServer = (DictionaryTestHelper)null; - var className = $"{nameof(DictionaryTestHelper)}"; - var clientsInitialized = new Dictionary(); - - var validateTimeout = new TimeoutHelper(0.25f); - - foreach (var client in m_Clients) - { - var ownerInitialized = false; - var serverInitialized = false; - /////////////////////////////////////////////////////////////////////////// - // Dictionary> nested dictionaries - compDictionary = client.LocalClient.PlayerObject.GetComponent(); - compDictionaryServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances(), validateTimeout); - if (initialize) - { - if (validateTimeout.HasTimedOut()) - { - m_InitializedStatus.AppendLine($"[Client -{client.LocalClientId}][Owner] Failed validation: {compDictionary.GetLog()}"); - } - else - { - m_InitializedStatus.AppendLine($"[Client -{client.LocalClientId}][Owner] Passed validation!"); - } - ownerInitialized = !validateTimeout.HasTimedOut(); - } - else - { - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - } - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances(), validateTimeout); - if (initialize) - { - if (validateTimeout.HasTimedOut()) - { - m_InitializedStatus.AppendLine($"[Client -{client.LocalClientId}][Server] Failed validation: {compDictionaryServer.GetLog()}"); - } - else - { - m_InitializedStatus.AppendLine($"[Client -{client.LocalClientId}][Server] Passed validation!"); - } - serverInitialized = !validateTimeout.HasTimedOut(); - } - else - { - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - } - - if (initialize) - { - clientsInitialized.Add(client.LocalClientId, ownerInitialized & serverInitialized); - } - } - - if (initialize) - { - m_IsInitialized = true; - foreach (var entry in clientsInitialized) - { - if (!entry.Value) - { - m_IsInitialized = false; - break; - } - } - } - } - - private void ValidateClientsFlat(NetworkManager clientBeingTested) - { - if (!m_EnableDebug) - { - return; - } - VerboseDebug($">>>>>>>>>>>>>>>>>>>>>>>>>[{clientBeingTested.name}][{m_Stage}][Validation]<<<<<<<<<<<<<<<<<<<<<<<<< "); - m_Stage++; - var compDictionary = (DictionaryTestHelper)null; - var compDictionaryServer = (DictionaryTestHelper)null; - var className = $"{nameof(DictionaryTestHelper)}"; - foreach (var client in m_Clients) - { - /////////////////////////////////////////////////////////////////////////// - // Dictionary> nested dictionaries - compDictionary = client.LocalClient.PlayerObject.GetComponent(); - compDictionaryServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - Assert.True(compDictionary.ValidateInstances(), $"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - Assert.True(compDictionaryServer.ValidateInstances(), $"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - } - } - - - [UnityTest] - public IEnumerator TestDictionaryCollections() - { - var compDictionary = (DictionaryTestHelper)null; - var compDictionaryServer = (DictionaryTestHelper)null; - var className = $"{nameof(DictionaryTestHelper)}"; - - m_Clients = m_ClientNetworkManagers.ToList(); - if (m_ServerNetworkManager.IsHost) - { - m_Clients.Insert(0, m_ServerNetworkManager); - } - - m_CurrentKey = 1000; - - if (m_EnableDebug) - { - VerboseDebug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Init Values <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); - foreach (var client in m_Clients) - { - compDictionary = client.LocalClient.PlayerObject.GetComponent(); - compDictionary.InitValues(); - compDictionaryServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - compDictionaryServer.InitValues(); - } - VerboseDebug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Init Check <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); - var count = 0; - while (count < 3) - { - m_InitializedStatus.Clear(); - foreach (var client in m_Clients) - { - yield return ValidateClients(client, true); - } - if (m_IsInitialized) - { - break; - } - count++; - m_Stage = 0; - } - - Assert.IsTrue(m_IsInitialized, $"Not all clients synchronized properly!\n {m_InitializedStatus.ToString()}"); - VerboseDebug(m_InitializedStatus.ToString()); - } - - VerboseDebug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BEGIN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); - foreach (var client in m_Clients) - { - /////////////////////////////////////////////////////////////////////////// - // Dictionary> nested dictionaries - compDictionary = client.LocalClient.PlayerObject.GetComponent(); - compDictionaryServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - - ////////////////////////////////// - // Owner Add SerializableObject Entry - var newEntry = (GetNextKey(), SerializableObject.GetRandomObject()); - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Server-side add same key and SerializableObject prior to being added to the owner side - compDictionaryServer.ListCollectionOwner.Value.Add(newEntry.Item1, newEntry.Item2); - // Checking if dirty on server side should revert back to origina known current dictionary state - compDictionaryServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server add to owner write collection property failed to restore on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - // Server-side add the same key and SerializableObject to owner write permission (would throw key exists exception too if previous failed) - compDictionaryServer.ListCollectionOwner.Value.Add(newEntry.Item1, newEntry.Item2); - // Server-side add a completely new key and SerializableObject to to owner write permission property - compDictionaryServer.ListCollectionOwner.Value.Add(GetNextKey(), SerializableObject.GetRandomObject()); - // Both should be overridden by the owner-side update - - } - VerboseDebug($"[{compDictionary.name}][Owner] Adding Key: {newEntry.Item1}"); - // Add key and SerializableObject to owner side - compDictionary.Add(newEntry, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - - ValidateClientsFlat(client); - ////////////////////////////////// - // Server Add SerializableObject Entry - newEntry = (GetNextKey(), SerializableObject.GetRandomObject()); - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Client-side add same key and SerializableObject to server write permission property - compDictionary.ListCollectionServer.Value.Add(newEntry.Item1, newEntry.Item2); - // Checking if dirty on client side should revert back to origina known current dictionary state - compDictionary.ListCollectionServer.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client-{client.LocalClientId} add to server write collection property failed to restore on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - // Client-side add the same key and SerializableObject to server write permission property (would throw key exists exception too if previous failed) - compDictionary.ListCollectionServer.Value.Add(newEntry.Item1, newEntry.Item2); - // Client-side add a completely new key and SerializableObject to to server write permission property - compDictionary.ListCollectionServer.Value.Add(GetNextKey(), SerializableObject.GetRandomObject()); - // Both should be overridden by the server-side update - } - VerboseDebug($"[{compDictionaryServer.name}][Server] Adding Key: {newEntry.Item1}"); - compDictionaryServer.Add(newEntry, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - ////////////////////////////////// - // Owner Remove SerializableObject Entry - var index = Random.Range(0, compDictionary.ListCollectionOwner.Value.Keys.Count - 1); - var valueInt = compDictionary.ListCollectionOwner.Value.Keys.ToList()[index]; - compDictionary.Remove(valueInt, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - - ////////////////////////////////// - // Server Remove SerializableObject Entry - index = Random.Range(0, compDictionary.ListCollectionServer.Value.Keys.Count - 1); - valueInt = compDictionary.ListCollectionServer.Value.Keys.ToList()[index]; - compDictionaryServer.Remove(valueInt, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - - ValidateClientsFlat(client); - //////////////////////////////////// - // Owner Change SerializableObject Entry - var randomObject = SerializableObject.GetRandomObject(); - if (compDictionary.ListCollectionOwner.Value.Keys.Count != 0) - { - if (compDictionary.ListCollectionOwner.Value.Keys.Count == 1) - { - index = 0; - valueInt = compDictionary.ListCollectionOwner.Value.Keys.ToList()[0]; - } - else - { - index = Random.Range(0, compDictionary.ListCollectionOwner.Value.Keys.Count - 1); - valueInt = compDictionary.ListCollectionOwner.Value.Keys.ToList()[index]; - } - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Server-side update same key value prior to being updated to the owner side - compDictionaryServer.ListCollectionOwner.Value[valueInt] = randomObject; - // Checking if dirty on server side should revert back to origina known current dictionary state - compDictionaryServer.ListCollectionOwner.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Server update collection entry value to local owner write collection property failed to restore on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - // Server-side update same key but with different value prior to being updated to the owner side - compDictionaryServer.ListCollectionOwner.Value[valueInt] = SerializableObject.GetRandomObject(); - if (compDictionaryServer.ListCollectionOwner.Value.Keys.Count > 1) - { - // Server-side update different key with different value prior to being updated to the owner side - compDictionaryServer.ListCollectionOwner.Value[compDictionaryServer.ListCollectionOwner.Value.Keys.ToList()[(index + 1) % compDictionaryServer.ListCollectionOwner.Value.Keys.Count]] = SerializableObject.GetRandomObject(); - } - // Owner-side update should force restore to current known value before updating to the owner's state update of the original index and SerializableObject - } - - compDictionary.ListCollectionOwner.Value[valueInt] = randomObject; - compDictionary.ListCollectionOwner.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - } - - ////////////////////////////////// - // Server Change SerializableObject - if (compDictionaryServer.ListCollectionServer.Value.Keys.Count != 0) - { - if (compDictionaryServer.ListCollectionServer.Value.Keys.Count == 1) - { - index = 0; - valueInt = compDictionaryServer.ListCollectionServer.Value.Keys.ToList()[0]; - } - else - { - index = Random.Range(0, compDictionaryServer.ListCollectionServer.Value.Keys.Count - 1); - valueInt = compDictionaryServer.ListCollectionServer.Value.Keys.ToList()[index]; - } - - // Only test restore on non-host clients (otherwise a host is both server and client/owner) - if (!client.IsServer) - { - // Owner-side update same key value prior to being updated to the server side - compDictionary.ListCollectionServer.Value[valueInt] = randomObject; - // Checking if dirty on owner side should revert back to origina known current dictionary state - compDictionary.ListCollectionServer.IsDirty(); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Client-{client.LocalClientId} update collection entry value to local server write collection property failed to restore on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - - // Owner-side update same key but with different value prior to being updated to the server side - compDictionary.ListCollectionServer.Value[valueInt] = SerializableObject.GetRandomObject(); - - if (compDictionary.ListCollectionServer.Value.Keys.Count > 1) - { - // Owner-side update different key with different value prior to being updated to the server side - compDictionary.ListCollectionServer.Value[compDictionary.ListCollectionServer.Value.Keys.ToList()[(index + 1) % compDictionary.ListCollectionServer.Value.Keys.Count]] = SerializableObject.GetRandomObject(); - } - // Server-side update should force restore to current known value before updating to the server's state update of the original index and SerializableObject - } - - compDictionaryServer.ListCollectionServer.Value[valueInt] = SerializableObject.GetRandomObject(); - compDictionaryServer.ListCollectionServer.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - } - ValidateClientsFlat(client); - - //////////////////////////////////// - // Owner Clear - compDictionary.Clear(ListTestHelperBase.Targets.Owner); - VerboseDebug($"[{compDictionary.name}] Clearing dictionary.."); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Clear - VerboseDebug($"[{compDictionaryServer.name}] Clearing dictionary.."); - compDictionaryServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - - //////////////////////////////////// - // Owner Full Set Dictionary - compDictionary.FullSet(DictionaryTestHelper.GetDictionaryValues(), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Full Set Dictionary - compDictionaryServer.FullSet(DictionaryTestHelper.GetDictionaryValues(), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - if (m_EnableDebug) - { - yield return ValidateClients(client); - m_Stage = 0; - } - } - } - - [UnityTest] - public IEnumerator TestDictionaryNestedCollections() - { - var compDictionary = (NestedDictionaryTestHelper)null; - var compDictionaryServer = (NestedDictionaryTestHelper)null; - var className = $"{nameof(NestedDictionaryTestHelper)}"; - - var clientList = m_ClientNetworkManagers.ToList(); - if (m_ServerNetworkManager.IsHost) - { - clientList.Insert(0, m_ServerNetworkManager); - } - - m_CurrentKey = 1000; - - foreach (var client in clientList) - { - /////////////////////////////////////////////////////////////////////////// - // Dictionary> nested dictionaries - compDictionary = client.LocalClient.PlayerObject.GetComponent(); - compDictionaryServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - - ////////////////////////////////// - // Owner Add Dictionary - compDictionary.Add((GetNextKey(), NestedDictionaryTestHelper.GetDictionaryValues()), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Add Dictionary - compDictionaryServer.Add((GetNextKey(), NestedDictionaryTestHelper.GetDictionaryValues()), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - ////////////////////////////////// - // Owner Remove Dictionary - var index = Random.Range(0, compDictionary.ListCollectionOwner.Value.Keys.Count - 1); - var valueInt = compDictionary.ListCollectionOwner.Value.Keys.ToList()[index]; - compDictionary.Remove(valueInt, ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Remove Dictionary - index = Random.Range(0, compDictionaryServer.ListCollectionOwner.Value.Keys.Count - 1); - valueInt = compDictionaryServer.ListCollectionOwner.Value.Keys.ToList()[index]; - compDictionaryServer.Remove(valueInt, ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - - //////////////////////////////////// - // Owner Change Dictionary - index = Random.Range(0, compDictionary.ListCollectionOwner.Value.Keys.Count - 1); - valueInt = compDictionary.ListCollectionOwner.Value.Keys.ToList()[index]; - compDictionary.ListCollectionOwner.Value[valueInt] = NestedDictionaryTestHelper.GetDictionaryValues(); - compDictionary.ListCollectionOwner.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} change failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Change Dictionary - index = Random.Range(0, compDictionaryServer.ListCollectionOwner.Value.Keys.Count - 1); - valueInt = compDictionaryServer.ListCollectionOwner.Value.Keys.ToList()[index]; - compDictionaryServer.ListCollectionServer.Value[index] = NestedDictionaryTestHelper.GetDictionaryValues(); - compDictionaryServer.ListCollectionServer.CheckDirtyState(); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server change failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - //////////////////////////////////// - // Owner Full Set Nested Dictionaries - compDictionary.FullSet(NestedDictionaryTestHelper.GetNestedDictionaryValues(), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Full Set Nested Dictionaries - compDictionaryServer.FullSet(NestedDictionaryTestHelper.GetNestedDictionaryValues(), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - //////////////////////////////////// - // Owner Clear - compDictionary.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compDictionary.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {className} {compDictionary.name}! {compDictionary.GetLog()}"); - ////////////////////////////////// - // Server Clear - compDictionaryServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {className} {compDictionaryServer.name}! {compDictionaryServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionary.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compDictionary.OwnerClientId}'s {className} {compDictionary.name} component match! {compDictionary.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compDictionaryServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compDictionaryServer.OwnerClientId}'s {className} {compDictionaryServer.name} component match! {compDictionaryServer.GetLog()}"); - } - } - - [UnityTest] - public IEnumerator TestHashSetBuiltInTypeCollections() - { - var compHashSet = (HashSetBaseTypeTestHelper)null; - var compHashSetServer = (HashSetBaseTypeTestHelper)null; - var className = $"{nameof(HashSetBaseTypeTestHelper)}"; - - var clientList = m_ClientNetworkManagers.ToList(); - if (m_ServerNetworkManager.IsHost) - { - clientList.Insert(0, m_ServerNetworkManager); - } - - m_CurrentKey = 1000; - - foreach (var client in clientList) - { - /////////////////////////////////////////////////////////////////////////// - // HashSet Single dimension list - compHashSet = client.LocalClient.PlayerObject.GetComponent(); - compHashSetServer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][client.LocalClientId].GetComponent(); - yield return WaitForConditionOrTimeOut(() => compHashSet.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compHashSet.OwnerClientId}'s {className} {compHashSet.name} component match! {compHashSet.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compHashSetServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compHashSetServer.OwnerClientId}'s {className} {compHashSetServer.name} component match! {compHashSetServer.GetLog()}"); - - ////////////////////////////////// - // Owner Add Item - compHashSet.Add(Random.Range(ushort.MinValue, ushort.MaxValue), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compHashSet.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} add failed to synchronize on {className} {compHashSet.name}! {compHashSet.GetLog()}"); - ////////////////////////////////// - // Server Add Item - compHashSetServer.Add(Random.Range(ushort.MinValue, ushort.MaxValue), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compHashSetServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server add failed to synchronize on {className} {compHashSetServer.name}! {compHashSetServer.GetLog()}"); - ////////////////////////////////// - // Owner Remove Item - var index = Random.Range(0, compHashSet.ListCollectionOwner.Value.Count - 1); - compHashSet.Remove(compHashSet.ListCollectionOwner.Value.ElementAt(index), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compHashSet.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} remove failed to synchronize on {className} {compHashSet.name}! {compHashSet.GetLog()}"); - ////////////////////////////////// - // Server Remove Item - index = Random.Range(0, compHashSetServer.ListCollectionOwner.Value.Count - 1); - compHashSetServer.Remove(compHashSetServer.ListCollectionOwner.Value.ElementAt(index), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compHashSetServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server remove failed to synchronize on {className} {compHashSetServer.name}! {compHashSetServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compHashSet.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compHashSet.OwnerClientId}'s {className} {compHashSet.name} component match! {compHashSet.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compHashSetServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compHashSetServer.OwnerClientId}'s {className} {compHashSetServer.name} component match! {compHashSetServer.GetLog()}"); - - //////////////////////////////////// - // Owner Full Set HashSet Values - compHashSet.FullSet(HashSetBaseTypeTestHelper.GetHashSetValues(), ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compHashSet.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} full set failed to synchronize on {className} {compHashSet.name}! {compHashSet.GetLog()}"); - ////////////////////////////////// - // Server Full Set HashSet Values - compHashSetServer.FullSet(HashSetBaseTypeTestHelper.GetHashSetValues(), ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compHashSetServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server full set failed to synchronize on {className} {compHashSetServer.name}! {compHashSetServer.GetLog()}"); - - //////////////////////////////////// - // Owner Clear - compHashSet.Clear(ListTestHelperBase.Targets.Owner); - yield return WaitForConditionOrTimeOut(() => compHashSet.CompareTrackedChanges(ListTestHelperBase.Targets.Owner)); - AssertOnTimeout($"Client-{client.LocalClientId} clear failed to synchronize on {className} {compHashSet.name}! {compHashSet.GetLog()}"); - ////////////////////////////////// - // Server Clear - compHashSetServer.Clear(ListTestHelperBase.Targets.Server); - yield return WaitForConditionOrTimeOut(() => compHashSetServer.CompareTrackedChanges(ListTestHelperBase.Targets.Server)); - AssertOnTimeout($"Server clear failed to synchronize on {className} {compHashSetServer.name}! {compHashSetServer.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compHashSet.ValidateInstances()); - AssertOnTimeout($"[Owner] Not all instances of client-{compHashSet.OwnerClientId}'s {className} {compHashSet.name} component match! {compHashSet.GetLog()}"); - - yield return WaitForConditionOrTimeOut(() => compHashSetServer.ValidateInstances()); - AssertOnTimeout($"[Server] Not all instances of client-{compHashSetServer.OwnerClientId}'s {className} {compHashSetServer.name} component match! {compHashSetServer.GetLog()}"); - } - - } - } - - [TestFixture(HostOrServer.DAHost, CollectionTypes.List)] - [TestFixture(HostOrServer.DAHost, CollectionTypes.Dictionary)] - [TestFixture(HostOrServer.Host, CollectionTypes.List)] - [TestFixture(HostOrServer.Host, CollectionTypes.Dictionary)] - [TestFixture(HostOrServer.Server, CollectionTypes.List)] - [TestFixture(HostOrServer.Server, CollectionTypes.Dictionary)] - public class NetworkVariableCollectionsChangingTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - public enum CollectionTypes - { - Dictionary, - List, - } - private StringBuilder m_ErrorLog = new StringBuilder(); - private CollectionTypes m_CollectionType; - private GameObject m_TestPrefab; - private NetworkObject m_Instance; - - public NetworkVariableCollectionsChangingTests(HostOrServer hostOrServer, CollectionTypes collectionType) : base(hostOrServer) - { - m_CollectionType = collectionType; - } - - protected override void OnServerAndClientsCreated() - { - m_TestPrefab = CreateNetworkObjectPrefab("TestObject"); - if (m_CollectionType == CollectionTypes.Dictionary) - { - m_TestPrefab.AddComponent(); - } - else - { - m_TestPrefab.AddComponent(); - } - if (m_DistributedAuthority) - { - var networkObject = m_TestPrefab.GetComponent(); - networkObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.Transferable); - } - base.OnServerAndClientsCreated(); - } - - private bool AllInstancesSpawned() - { - if (!UseCMBService()) - { - if (!m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(m_Instance.NetworkObjectId)) - { - return false; - } - } - - foreach (var client in m_ClientNetworkManagers) - { - if (!client.SpawnManager.SpawnedObjects.ContainsKey(m_Instance.NetworkObjectId)) - { - return false; - } - } - return true; - } - - private Dictionary m_NetworkManagers = new Dictionary(); - - private bool ValidateAllInstances() - { - if (!m_NetworkManagers.ContainsKey(m_Instance.OwnerClientId)) - { - return false; - } - - if (!m_NetworkManagers[m_Instance.OwnerClientId].SpawnManager.SpawnedObjects.ContainsKey(m_Instance.NetworkObjectId)) - { - return false; - } - - var ownerNetworkManager = m_NetworkManagers[m_Instance.OwnerClientId]; - - var ownerClientInstance = m_NetworkManagers[m_Instance.OwnerClientId].SpawnManager.SpawnedObjects[m_Instance.NetworkObjectId].GetComponent(); - - foreach (var client in m_NetworkManagers) - { - if (client.Value == ownerNetworkManager) - { - continue; - } - - var otherInstance = client.Value.SpawnManager.SpawnedObjects[m_Instance.NetworkObjectId].GetComponent(); - if (!ownerClientInstance.ValidateAgainst(otherInstance)) - { - return false; - } - } - return true; - } - - private bool OwnershipChangedOnAllClients(ulong expectedOwner) - { - m_ErrorLog.Clear(); - foreach (var client in m_NetworkManagers) - { - var otherInstance = client.Value.SpawnManager.SpawnedObjects[m_Instance.NetworkObjectId].GetComponent(); - if (otherInstance.OwnerClientId != expectedOwner) - { - m_ErrorLog.AppendLine($"Client-{client.Value.LocalClientId} instance of {m_Instance.name} still shows the owner is Client-{otherInstance.OwnerClientId} when it should be Client-{expectedOwner}!"); - return false; - } - } - return true; - } - - private BaseCollectionUpdateHelper GetOwnerInstance() - { - var ownerNetworkManager = m_NetworkManagers[m_Instance.OwnerClientId]; - return m_NetworkManagers[m_Instance.OwnerClientId].SpawnManager.SpawnedObjects[m_Instance.NetworkObjectId].GetComponent(); - } - - /// - /// Gets the authority instance. - /// Client-Server: will always return the server-side instance - /// Distributed Authority: will always return the owner - /// - /// authority instance - private BaseCollectionUpdateHelper GetAuthorityInstance() - { - if (m_DistributedAuthority) - { - return GetOwnerInstance(); - } - else - { - return m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_Instance.NetworkObjectId].GetComponent(); - } - } - - [UnityTest] - public IEnumerator CollectionAndOwnershipChangingTest() - { - BaseCollectionUpdateHelper.VerboseMode = m_EnableVerboseDebug; - var runWaitPeriod = new WaitForSeconds(0.5f); - m_NetworkManagers.Clear(); - if (!UseCMBService() && m_UseHost) - { - m_NetworkManagers.Add(m_ServerNetworkManager.LocalClientId, m_ServerNetworkManager); - } - foreach (var client in m_ClientNetworkManagers) - { - m_NetworkManagers.Add(client.LocalClientId, client); - } - - var authorityNetworkManager = UseCMBService() || !m_UseHost ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - - var instance = SpawnObject(m_TestPrefab, authorityNetworkManager); - m_Instance = instance.GetComponent(); - var helper = instance.GetComponent(); - var currentOwner = helper.OwnerClientId; - yield return WaitForConditionOrTimeOut(AllInstancesSpawned); - AssertOnTimeout($"[Pre][1st Phase] Timed out waiting for all clients to spawn {m_Instance.name}!"); - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Start); - yield return runWaitPeriod; - - // Update values, validate values, change owner, updates values, and repeat until all clients have been the owner at least once - for (int i = 0; i < 4; i++) - { - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Pause); - yield return WaitForConditionOrTimeOut(ValidateAllInstances); - AssertOnTimeout($"[1st Phase] Timed out waiting for all clients to validdate their values!"); - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Start); - yield return s_DefaultWaitForTick; - - currentOwner = GetAuthorityInstance().ChangeOwner(); - Assert.IsFalse(currentOwner == ulong.MaxValue, "A non-authority instance attempted to change ownership!"); - - yield return WaitForConditionOrTimeOut(() => OwnershipChangedOnAllClients(currentOwner)); - AssertOnTimeout($"[1st Phase] Timed out waiting for all clients to change ownership!\n {m_ErrorLog.ToString()}"); - helper = GetOwnerInstance(); - yield return runWaitPeriod; - } - - // Now reset the values - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Pause); - helper.Clear(); - - // Validate all instances are reset - yield return WaitForConditionOrTimeOut(ValidateAllInstances); - AssertOnTimeout($"[Pre][2nd Phase]Timed out waiting for all clients to validdate their values!"); - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Start); - - // Update, change ownership, and repeat until all clients have been the owner at least once - for (int i = 0; i < 4; i++) - { - yield return runWaitPeriod; - currentOwner = GetAuthorityInstance().ChangeOwner(); - Assert.IsFalse(currentOwner == ulong.MaxValue, "A non-authority instance attempted to change ownership!"); - yield return WaitForConditionOrTimeOut(() => OwnershipChangedOnAllClients(currentOwner)); - AssertOnTimeout($"[2nd Phase] Timed out waiting for all clients to change ownership!"); - helper = GetOwnerInstance(); - } - - helper.SetState(BaseCollectionUpdateHelper.HelperStates.Pause); - yield return WaitForConditionOrTimeOut(ValidateAllInstances); - AssertOnTimeout($"[Last Validate] Timed out waiting for all clients to validdate their values!"); - } - } - - #region COLLECTION CHANGING COMPONENTS - /// - /// Helper class to test adding dictionary entries rapidly with frequent ownership changes. - /// This includes a companion integer that is continually incremented and used as the key value for each entry. - /// - public class DictionaryCollectionUpdateHelper : BaseCollectionUpdateHelper - { - private NetworkVariable> m_DictionaryCollection = new NetworkVariable>(new Dictionary(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - private NetworkVariable m_CurrentKeyValue = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - - protected override bool OnValidateAgainst(BaseCollectionUpdateHelper otherHelper) - { - var otherListHelper = otherHelper as DictionaryCollectionUpdateHelper; - var localValues = m_DictionaryCollection.Value; - var otherValues = otherListHelper.m_DictionaryCollection.Value; - - if (localValues.Count != otherValues.Count) - { - return false; - } - - foreach (var entry in m_DictionaryCollection.Value) - { - if (!otherValues.ContainsKey(entry.Key)) - { - return false; - } - - if (entry.Value != otherValues[entry.Key]) - { - return false; - } - } - return true; - } - protected override void OnClear() - { - m_DictionaryCollection.Value.Clear(); - m_DictionaryCollection.CheckDirtyState(); - base.OnClear(); - } - - protected override void AddItem() - { - m_DictionaryCollection.Value.Add(m_CurrentKeyValue.Value, m_CurrentKeyValue.Value); - m_DictionaryCollection.CheckDirtyState(); - m_CurrentKeyValue.Value++; - } - } - - /// - /// Helper class to test adding list entries rapidly with frequent ownership changes - /// - public class ListCollectionUpdateHelper : BaseCollectionUpdateHelper - { - private NetworkVariable> m_ListCollection = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - - - protected override bool OnValidateAgainst(BaseCollectionUpdateHelper otherHelper) - { - var otherListHelper = otherHelper as ListCollectionUpdateHelper; - var localValues = m_ListCollection.Value; - var otherValues = otherListHelper.m_ListCollection.Value; - - if (localValues.Count != otherValues.Count) - { - return false; - } - - for (int i = 0; i < localValues.Count - 1; i++) - { - if (localValues[i] != i) - { - return false; - } - - if (localValues[i] != otherValues[i]) - { - return false; - } - } - return true; - } - - protected override void OnClear() - { - m_ListCollection.Value.Clear(); - m_ListCollection.CheckDirtyState(); - base.OnClear(); - } - - protected override void AddItem() - { - m_ListCollection.Value.Add(m_ListCollection.Value.Count); - m_ListCollection.CheckDirtyState(); - } - } - - /// - /// The base class to test rapidly adding items to a collection type - /// - public class BaseCollectionUpdateHelper : NetworkBehaviour - { - public static bool VerboseMode; - private const int k_OwnershipTickDelay = 1; - - public enum HelperStates - { - Stop, - Start, - Pause, - ClearToChangeOwner, - ChangingOwner - } - public HelperStates HelperState { get; private set; } - - private int m_SendClearForOwnershipOnTick; - private ulong m_NextClient = 0; - private ulong m_ClientToSendClear = 0; - - public void SetState(HelperStates helperState) - { - HelperState = helperState; - } - - protected virtual bool OnValidateAgainst(BaseCollectionUpdateHelper otherHelper) - { - return true; - } - - public bool ValidateAgainst(BaseCollectionUpdateHelper otherHelper) - { - return OnValidateAgainst(otherHelper); - } - - public override void OnNetworkSpawn() - { - // Register for tick updates - NetworkManager.NetworkTickSystem.Tick += OnNetworkTick; - - base.OnNetworkSpawn(); - } - public override void OnNetworkDespawn() - { - NetworkManager.NetworkTickSystem.Tick -= OnNetworkTick; - base.OnNetworkDespawn(); - } - - protected virtual void OnClear() - { - } - - public void Clear() - { - OnClear(); - } - - protected virtual void AddItem() - { - } - - private bool CanUpdate() - { - return HelperState == HelperStates.Start; - } - - private void Update() - { - // Exit early if not spawn, updating is not enabled, or is not the owner - if (!IsSpawned || !CanUpdate() || !IsOwner) - { - return; - } - - AddItem(); - } - - protected override void OnOwnershipChanged(ulong previous, ulong current) - { - // When the ownership changes and the client is the owner, then immediately add an item to the collection - if (NetworkManager.LocalClientId == current) - { - AddItem(); - } - base.OnOwnershipChanged(previous, current); - } - - - /// - /// Sets the tick delay period of time to provide all in-flight deltas to be processed. - /// - private void SetTickDelay() - { - m_SendClearForOwnershipOnTick = NetworkManager.ServerTime.Tick + k_OwnershipTickDelay; - } - - /// - /// Changes the ownership - /// - /// next owner or ulong.MaxValue that means the authority did not invoke this method - public ulong ChangeOwner() - { - if (HasAuthority && !IsOwnershipChanging()) - { - var index = NetworkManager.ConnectedClientsIds.ToList().IndexOf(OwnerClientId); - index++; - index = index % NetworkManager.ConnectedClientsIds.Count; - m_NextClient = NetworkManager.ConnectedClientsIds[index]; - - // If we are in distributed authority and the authority or we are in client-server and the server, then make the change ourselves. - if (OwnerClientId == NetworkManager.LocalClientId && (NetworkManager.DistributedAuthorityMode || (!NetworkManager.DistributedAuthorityMode && NetworkManager.IsServer))) - { - HelperState = HelperStates.ChangingOwner; - SetTickDelay(); - Log($"Locally changing ownership to Client-{m_NextClient}"); - } - - if (!NetworkManager.DistributedAuthorityMode && NetworkManager.IsServer && OwnerClientId != NetworkManager.LocalClientId) - { - // If we are transitioning between a client to the host or client to client, - // send a "heads-up" Rpc to the client prior to changing ownership. The client - // will stop updating for the tick delay period and then send a confirmation - // to the host that it is clear to change ownership. - ChangingOwnershipRpc(RpcTarget.Single(OwnerClientId, RpcTargetUse.Temp)); - Log($"Remotely changing ownership to Client-{m_NextClient}"); - } - - return m_NextClient; - } - - return ulong.MaxValue; - } - - /// - /// Sent by the host to a client when ownership is transitioning from a client to - /// the host or to another client. - /// - [Rpc(SendTo.SpecifiedInParams)] - private void ChangingOwnershipRpc(RpcParams rpcParams = default) - { - // The sender is who we respond to that it is clear to change ownership - m_ClientToSendClear = rpcParams.Receive.SenderClientId; - HelperState = HelperStates.ClearToChangeOwner; - SetTickDelay(); - } - - /// - /// Notification that the current owner has stopped updating and ownership - /// updates can occur without missed updates. - /// - /// - [Rpc(SendTo.SpecifiedInParams)] - private void ChangingOwnershipClearRpc(RpcParams rpcParams = default) - { - HelperState = HelperStates.ChangingOwner; - SetTickDelay(); - Log($"Changing ownership to Client-{m_NextClient} based on ready request."); - } - - private bool IsOwnershipChanging() - { - return HelperState == HelperStates.ClearToChangeOwner || HelperState == HelperStates.ChangingOwner; - } - - private void OnNetworkTick() - { - if (!IsSpawned || !IsOwnershipChanging() || m_SendClearForOwnershipOnTick > NetworkManager.ServerTime.Tick) - { - return; - } - - if (HelperState == HelperStates.ChangingOwner) - { - NetworkObject.ChangeOwnership(m_NextClient); - Log($"Local Change ownership to Client-{m_NextClient} complete! New Owner is {NetworkObject.OwnerClientId} | Expected {m_NextClient}"); - } - else - { - ChangingOwnershipClearRpc(RpcTarget.Single(m_ClientToSendClear, RpcTargetUse.Temp)); - } - HelperState = HelperStates.Stop; - } - - protected void Log(string msg) - { - if (VerboseMode) - { - Debug.Log($"[Client-{NetworkManager.LocalClientId}] {msg}"); - } - } - } - #endregion - - #region HASHSET COMPONENT HELPERS - public class HashSetBaseTypeTestHelper : ListTestHelperBase, IHashSetTestHelperBase - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable> ListCollectionServer = new NetworkVariable>(new HashSet(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new HashSet(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>> NetworkVariableChanges = new Dictionary>>(); - - public bool ValidateInstances() - { - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!ListCollectionOwner.Value.SequenceEqual(otherOwnerCollection.Value)) - { - return false; - } - if (!ListCollectionServer.Value.SequenceEqual(otherServerCollection.Value)) - { - return false; - } - } - return true; - } - - private bool ChangesMatch(Dictionary> local, Dictionary> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (local[deltaType].Count != other[deltaType].Count) - { - LogMessage($"{deltaType}s did not match!"); - return false; - } - foreach (var value in local[deltaType]) - { - if (!other[deltaType].Contains(value)) - { - LogMessage($"Value ({value}) in local was not found on remote!"); - return false; - } - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} did not match!"); - return false; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return true; - } - - public static HashSet GetHashSetValues(int count = 5) - { - var hashSet = new HashSet(); - for (int i = 0; i < count; i++) - { - hashSet.Add(Random.Range(ushort.MinValue, ushort.MaxValue)); - } - return hashSet; - } - - public NetworkVariable> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public HashSet OnSetServerValues() - { - return GetHashSetValues(); - } - - public HashSet OnSetOwnerValues() - { - return GetHashSetValues(); - } - - public void Add(int value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value); - netVar.CheckDirtyState(); - } - - public void AddRange(HashSet values, Targets target) - { - var netVar = GetNetVar(target); - foreach (var value in values) - { - netVar.Value.Add(value); - } - netVar.CheckDirtyState(); - } - - public void Remove(int value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(value); - netVar.CheckDirtyState(); - } - - public void FullSet(HashSet values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, HashSet previous, HashSet current) - { - var contextTable = NetworkVariableChanges[target]; - - var whatWasAdded = current.Except(previous).ToHashSet(); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToHashSet(); - var whatWasNeitherAddedOrRemoved = current.Where((c) => previous.Contains(c) && !whatWasAdded.Contains(c)).ToHashSet(); - var whatChanged = whatWasNeitherAddedOrRemoved.Where((c) => previous.Contains(c) && !previous.Where((d) => d.Equals(c)).FirstOrDefault().Equals(c)).ToHashSet(); - var whatRemainedTheSame = whatWasNeitherAddedOrRemoved.Where((c) => !whatChanged.Contains(c)).ToHashSet(); - - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed] = whatChanged; - contextTable[DeltaTypes.UnChanged] = whatRemainedTheSame; - } - - public void OnServerListValuesChanged(HashSet previous, HashSet current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(HashSet previous, HashSet current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new HashSet()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new HashSet()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new HashSet()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new HashSet()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new HashSet()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new HashSet()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new HashSet()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new HashSet()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionOwner.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - #endregion - - #region DICTIONARY COMPONENT HELPERS - public class NestedDictionaryTestHelper : ListTestHelperBase, IDictionaryTestHelperBase> - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new Dictionary>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new Dictionary>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); - - private bool CompareDictionaries(ulong clientId, Dictionary first, Dictionary second) - { - foreach (var entry in first) - { - if (!second.ContainsKey(entry.Key)) - { - LogMessage($"Client-{clientId} has no key entry for ({entry.Key})!"); - return false; - } - var seconValue = second[entry.Key]; - if (!entry.Value.Equals(seconValue)) - { - LogMessage($"Client-{clientId} value ({seconValue} does not equal ({entry.Value})!"); - return false; - } - } - return true; - } - - private bool CompareNestedDictionaries(ulong clientId, Dictionary> first, Dictionary> second) - { - foreach (var entry in first) - { - if (!second.ContainsKey(entry.Key)) - { - LogMessage($"Client-{clientId} has no key entry for ({entry.Key})!"); - return false; - } - var secondValue = second[entry.Key]; - if (!CompareDictionaries(clientId, entry.Value, secondValue)) - { - LogMessage($"Client-{clientId} value root Key ({entry.Key}) dictionary does not equal the local dictionary!"); - return false; - } - } - return true; - } - - public bool ValidateInstances() - { - LogStart(); - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - LogMessage($"Client-{clientId} has no entry!"); - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - LogMessage($"Client-{clientId} has no instance entry of NetworkObject ({NetworkObjectId})!"); - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - - if (!CompareNestedDictionaries(clientId, ListCollectionOwner.Value, otherOwnerCollection.Value)) - { - LogMessage($"Client-{clientId} did not synchronize properly with the owner collection!"); - return false; - } - - if (!CompareNestedDictionaries(clientId, ListCollectionServer.Value, otherServerCollection.Value)) - { - LogMessage($"Client-{clientId} did not synchronize properly with the server collection!"); - return false; - } - } - return true; - } - - private bool ChangesMatch(ulong clientId, Dictionary>> local, Dictionary>> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (local[deltaType].Count != other[deltaType].Count) - { - LogMessage($"{deltaType}s count did not match!"); - return false; - } - if (!CompareNestedDictionaries(clientId, local[deltaType], other[deltaType])) - { - LogMessage($"{deltaType}s values did not match!"); - return false; - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(clientId, localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} failed to synchronize properly!"); - return false; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return true; - } - - public static Dictionary GetDictionaryValues(int count = 5) - { - var dictionary = new Dictionary(); - for (int i = 0; i < count; i++) - { - dictionary.Add(i, SerializableObject.GetRandomObject()); - } - return dictionary; - } - - public static Dictionary> GetNestedDictionaryValues(int count = 5) - { - var dictionary = new Dictionary>(); - for (int i = 0; i < count; i++) - { - dictionary.Add(i, GetDictionaryValues()); - } - return dictionary; - } - - public NetworkVariable>> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public Dictionary> OnSetServerValues() - { - - return GetNestedDictionaryValues(); - } - - public Dictionary> OnSetOwnerValues() - { - return GetNestedDictionaryValues(); - } - - - public bool UpdateValue((int, Dictionary) value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - if (netVar.Value.ContainsKey(value.Item1)) - { - netVar.Value[value.Item1] = value.Item2; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - return true; - } - return false; - } - - public void Add((int, Dictionary) value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value.Item1, value.Item2); - netVar.CheckDirtyState(); - } - - public void Remove(int key, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(key); - netVar.CheckDirtyState(); - } - - public void FullSet(Dictionary> values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, Dictionary> previous, Dictionary> current) - { - var contextTable = NetworkVariableChanges[target]; - - var whatWasAdded = current.Except(previous).ToDictionary(item => item.Key, item => item.Value); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - var whatWasNeitherAddedOrRemoved = current.Where((c) => previous.Contains(c) && !whatWasAdded.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - var whatChanged = whatWasNeitherAddedOrRemoved.Where((c) => previous.Contains(c) && !previous.Where((d) => d.Equals(c)).FirstOrDefault().Equals(c)).ToDictionary(item => item.Key, item => item.Value); - var whatRemainedTheSame = whatWasNeitherAddedOrRemoved.Where((c) => !whatChanged.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed] = whatChanged; - contextTable[DeltaTypes.UnChanged] = whatRemainedTheSame; - } - - public void OnServerListValuesChanged(Dictionary> previous, Dictionary> current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(Dictionary> previous, Dictionary> current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new Dictionary>()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new Dictionary>()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionOwner.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - - public class DictionaryTestHelper : ListTestHelperBase, IDictionaryTestHelperBase - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable> ListCollectionServer = new NetworkVariable>(new Dictionary(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new Dictionary(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>> NetworkVariableChanges = new Dictionary>>(); - - private bool CompareDictionaries(ulong clientId, Dictionary first, Dictionary second) - { - foreach (var entry in first) - { - if (!second.ContainsKey(entry.Key)) - { - LogMessage($"Client-{clientId} has no key entry for ({entry.Key})!"); - return false; - } - var seconValue = second[entry.Key]; - if (!entry.Value.Equals(seconValue)) - { - LogMessage($"Client-{clientId} value ({seconValue} does not equal ({entry.Value})!"); - return false; - } - } - return true; - } - - public bool ValidateInstances() - { - LogStart(); - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - LogMessage($"Client-{clientId} has no entry!"); - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - LogMessage($"Client-{clientId} has no instance entry of NetworkObject ({NetworkObjectId})!"); - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!CompareDictionaries(clientId, ListCollectionOwner.Value, otherOwnerCollection.Value)) - { - LogMessage($"Client-{clientId} did not synchronize properly with the owner collection!"); - return false; - } - - if (!CompareDictionaries(clientId, ListCollectionServer.Value, otherServerCollection.Value)) - { - LogMessage($"Client-{clientId} did not synchronize properly with the server collection!"); - return false; - } - } - return true; - } - - private bool ChangesMatch(ulong clientId, Dictionary> local, Dictionary> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (local[deltaType].Count != other[deltaType].Count) - { - LogMessage($"{deltaType}s count did not match!"); - return false; - } - if (!CompareDictionaries(clientId, local[deltaType], other[deltaType])) - { - LogMessage($"{deltaType}s values did not match!"); - return false; - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(clientId, localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} failed to synchronize properly!"); - return false; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return true; - } - - public static Dictionary GetDictionaryValues(int count = 5) - { - var dictionary = new Dictionary(); - for (int i = 0; i < count; i++) - { - dictionary.Add(i, SerializableObject.GetRandomObject()); - } - return dictionary; - } - - public NetworkVariable> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public Dictionary OnSetServerValues() - { - return GetDictionaryValues(); - } - - public Dictionary OnSetOwnerValues() - { - return GetDictionaryValues(); - } - - - public bool UpdateValue((int, SerializableObject) value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - if (netVar.Value.ContainsKey(value.Item1)) - { - netVar.Value[value.Item1] = value.Item2; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - return true; - } - return false; - } - - public void Add((int, SerializableObject) value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value.Item1, value.Item2); - netVar.CheckDirtyState(); - } - - public void Remove(int key, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(key); - netVar.CheckDirtyState(); - } - - public void FullSet(Dictionary values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, Dictionary previous, Dictionary current) - { - var contextTable = NetworkVariableChanges[target]; - - var whatWasAdded = current.Except(previous).ToDictionary(item => item.Key, item => item.Value); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - var whatWasNeitherAddedOrRemoved = current.Where((c) => previous.Contains(c) && !whatWasAdded.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - var whatChanged = whatWasNeitherAddedOrRemoved.Where((c) => previous.Contains(c) && !previous.Where((d) => d.Equals(c)).FirstOrDefault().Equals(c)).ToDictionary(item => item.Key, item => item.Value); - var whatRemainedTheSame = whatWasNeitherAddedOrRemoved.Where((c) => !whatChanged.Contains(c)).ToDictionary(item => item.Key, item => item.Value); - - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed] = whatChanged; - contextTable[DeltaTypes.UnChanged] = whatRemainedTheSame; - } - - public void OnServerListValuesChanged(Dictionary previous, Dictionary current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(Dictionary previous, Dictionary current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new Dictionary()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new Dictionary()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new Dictionary()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new Dictionary()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new Dictionary()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new Dictionary()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new Dictionary()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new Dictionary()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (!IsDebugMode) - { - InitValues(); - } - } - - public void InitValues() - { - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionOwner.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - } - - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - #endregion - - #region INETWORKSERIALIZABLE LIST TEST COMPONENT HELPERS - public class SerializableObject : INetworkSerializable, IEquatable - { - public static SerializableObject GetRandomObject() - { - var serializableObject = new SerializableObject() - { - FloatValue = Random.Range(float.MinValue, float.MaxValue), - IntValue = Random.Range(ushort.MinValue, ushort.MaxValue), - LongValue = Random.Range(int.MinValue, int.MaxValue), - }; - return serializableObject; - } - - public static List GetListOfRandomObjects(int count) - { - var list = new List(); - for (int i = 0; i < count; i++) - { - list.Add(GetRandomObject()); - } - return list; - } - - public static List> GetListOfListOfRandomObjects(int numberOfLists, int countPerList) - { - var list = new List>(); - for (int i = 0; i < numberOfLists; i++) - { - list.Add(GetListOfRandomObjects(countPerList)); - } - return list; - } - - public int IntValue; - public long LongValue; - public float FloatValue; - - public override string ToString() - { - return $"{IntValue},{LongValue},{FloatValue}"; - } - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref IntValue); - serializer.SerializeValue(ref LongValue); - serializer.SerializeValue(ref FloatValue); - } - - public bool Equals(SerializableObject other) - { - return IntValue.Equals(other.IntValue) && LongValue.Equals(other.LongValue) && FloatValue.Equals(other.FloatValue); - } - - } - - public class ListTestHelperListSerializableObject : ListTestHelperBase, IListTestHelperBase> - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); - - public bool ValidateInstances() - { - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!CompareBothItems(ListCollectionOwner.Value, otherOwnerCollection.Value)) - { - return false; - } - if (!CompareBothItems(ListCollectionServer.Value, otherServerCollection.Value)) - { - return false; - } - } - return true; - } - - private bool CompareBothItems(List> first, List> second) - { - if (first.Count != second.Count) - { - LogMessage($"Local count ({first.Count}) did not match remote count ({second.Count})!"); - return false; - } - for (int i = 0; i < first.Count; i++) - { - if (!first[i].SequenceEqual(second[i])) - { - LogMessage($"Sequence set ({i}) does not match! Local[{i}].Count = {first[i].Count} Remote[{i}].Count = {second[i].Count}."); - if (first[i].Count == second[i].Count) - { - var subBuilder = new StringBuilder(); - for (int j = 0; j < first[i].Count; j++) - { - subBuilder.Append($"[{first[i][j]}][{second[i][j]}]"); - } - - LogMessage($"Compared: {subBuilder}"); - } - return false; - } - } - return true; - } - - private bool ChangesMatch(Dictionary>> local, Dictionary>> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (!CompareBothItems(local[deltaType], other[deltaType])) - { - LogMessage($"{deltaType}s did not match!"); - return false; - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - var trackChangesSuccess = true; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - trackChangesSuccess = false; - break; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - trackChangesSuccess = false; - break; - } - - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} did not match!"); - trackChangesSuccess = false; - break; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return trackChangesSuccess; - } - - private List> GetInitialValues() - { - var rootList = new List>(); - for (int i = 0; i < 10; i++) - { - rootList.Add(SerializableObject.GetListOfRandomObjects(5)); - } - return rootList; - } - - public NetworkVariable>> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public List> OnSetServerValues() - { - return GetInitialValues(); - } - - public List> OnSetOwnerValues() - { - return GetInitialValues(); - } - - - public void UpdateValue(List value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - var index = netVar.Value.IndexOf(value); - netVar.Value[index] = value; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Add(List value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value); - netVar.CheckDirtyState(); - } - - public void AddRange(List> values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.AddRange(values); - netVar.CheckDirtyState(); - } - - public void Insert(List value, int index, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - netVar.Value.Insert(index, value); - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Remove(List value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(value); - netVar.CheckDirtyState(); - } - - public void FullSet(List> values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, List> previous, List> current) - { - var contextTable = NetworkVariableChanges[target]; - var whatWasAdded = current.Except(previous).ToList(); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToList(); - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed].Clear(); - contextTable[DeltaTypes.UnChanged].Clear(); - for (int i = 0; i < current.Count; i++) - { - if (previous.Count > i && !current[i].SequenceEqual(previous[i])) - { - contextTable[DeltaTypes.Changed].Add(current[i]); - } - else if (!whatWasAdded.Contains(current[i]) && previous.Contains(current[i])) - { - contextTable[DeltaTypes.UnChanged].Add(current[i]); - } - } - - } - - public void OnServerListValuesChanged(List> previous, List> current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(List> previous, List> current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new List>()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new List>()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionServer.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - - public class ListTestHelperSerializableObject : ListTestHelperBase, IListTestHelperBase - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable> ListCollectionServer = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>> NetworkVariableChanges = new Dictionary>>(); - - public bool ValidateInstances() - { - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!ListCollectionOwner.Value.SequenceEqual(otherOwnerCollection.Value)) - { - return false; - } - if (!ListCollectionServer.Value.SequenceEqual(otherServerCollection.Value)) - { - return false; - } - } - return true; - } - - private bool ChangesMatch(Dictionary> local, Dictionary> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (local[deltaType].Count != other[deltaType].Count) - { - LogMessage($"{deltaType}s did not match!"); - return false; - } - - for (int i = 0; i < local[deltaType].Count; i++) - { - if (!local[deltaType][i].Equals(other[deltaType][i])) - { - LogMessage($"Sequence set ({i}) does not match! Local[{i}] = {local[deltaType][i]} Remote[{i}].Count = {other[deltaType][i]}."); - return false; - } - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} did not match!"); - return false; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return true; - } - - private List GetInitialValues() - { - return SerializableObject.GetListOfRandomObjects(10); - } - - public NetworkVariable> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public List OnSetServerValues() - { - return GetInitialValues(); - } - - public List OnSetOwnerValues() - { - return GetInitialValues(); - } - - - public void UpdateValue(SerializableObject value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - var index = netVar.Value.IndexOf(value); - netVar.Value[index] = value; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Add(SerializableObject value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value); - netVar.CheckDirtyState(); - } - - public void AddRange(List values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.AddRange(values); - netVar.CheckDirtyState(); - } - - public void Insert(SerializableObject value, int index, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - netVar.Value.Insert(index, value); - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Remove(SerializableObject value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(value); - netVar.CheckDirtyState(); - } - - public void FullSet(List values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, List previous, List current) - { - var contextTable = NetworkVariableChanges[target]; - - var whatWasAdded = current.Except(previous).ToList(); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToList(); - var whatWasNeitherAddedOrRemoved = current.Where((c) => previous.Contains(c) && !whatWasAdded.Contains(c)).ToList(); - var whatChanged = whatWasNeitherAddedOrRemoved.Where((c) => previous.Contains(c) && !previous.Where((d) => d.Equals(c)).FirstOrDefault().Equals(c)).ToList(); - var whatRemainedTheSame = whatWasNeitherAddedOrRemoved.Where((c) => !whatChanged.Contains(c)).ToList(); - - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed] = whatChanged; - contextTable[DeltaTypes.UnChanged] = whatRemainedTheSame; - } - - public void OnServerListValuesChanged(List previous, List current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(List previous, List current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new List()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new List()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionOwner.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - - #endregion - - #region BUILT-IN LIST TEST COMPONENT HELPERS - public class ListTestHelperListInt : ListTestHelperBase, IListTestHelperBase> - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); - - public bool ValidateInstances() - { - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!CompareBothItems(ListCollectionOwner.Value, otherOwnerCollection.Value)) - { - return false; - } - if (!CompareBothItems(ListCollectionServer.Value, otherServerCollection.Value)) - { - return false; - } - } - return true; - } - - private bool CompareBothItems(List> first, List> second) - { - if (first.Count != second.Count) - { - LogMessage($"Local count ({first.Count}) did not match remote count ({second.Count})!"); - return false; - } - for (int i = 0; i < first.Count; i++) - { - if (!first[i].SequenceEqual(second[i])) - { - LogMessage($"Sequence set ({i}) does not match! Local[{i}].Count = {first[i].Count} Remote[{i}].Count = {second[i].Count}."); - if (first[i].Count == second[i].Count) - { - var subBuilder = new StringBuilder(); - for (int j = 0; j < first[i].Count; j++) - { - subBuilder.Append($"[{first[i][j]}][{second[i][j]}]"); - } - - LogMessage($"Compared: {subBuilder}"); - } - return false; - } - } - return true; - } - - private bool ChangesMatch(Dictionary>> local, Dictionary>> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (!CompareBothItems(local[deltaType], other[deltaType])) - { - LogMessage($"{deltaType}s did not match!"); - return false; - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - var trackChangesSuccess = true; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - trackChangesSuccess = false; - break; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - trackChangesSuccess = false; - break; - } - - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} did not match!"); - trackChangesSuccess = false; - break; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return trackChangesSuccess; - } - - private List> GetInitialValues() - { - var rootList = new List>(); - for (int i = 0; i < 10; i++) - { - var childList = new List(); - for (int j = 0; j < 10; j++) - { - childList.Add(Random.Range(short.MinValue, short.MaxValue)); - } - rootList.Add(childList); - } - return rootList; - } - - public NetworkVariable>> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public List> OnSetServerValues() - { - return GetInitialValues(); - } - - public List> OnSetOwnerValues() - { - return GetInitialValues(); - } - - - public void UpdateValue(List value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - var index = netVar.Value.IndexOf(value); - netVar.Value[index] = value; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Add(List value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value); - netVar.CheckDirtyState(); - } - - public void AddRange(List> values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.AddRange(values); - netVar.CheckDirtyState(); - } - - public void Insert(List value, int index, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - netVar.Value.Insert(index, value); - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Remove(List value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(value); - netVar.CheckDirtyState(); - } - - public void FullSet(List> values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, List> previous, List> current) - { - var contextTable = NetworkVariableChanges[target]; var whatWasAdded = current.Except(previous).ToList(); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToList(); - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed].Clear(); - contextTable[DeltaTypes.UnChanged].Clear(); - for (int i = 0; i < current.Count; i++) - { - if (previous.Count > i && !current[i].SequenceEqual(previous[i])) - { - contextTable[DeltaTypes.Changed].Add(current[i]); - } - else if (!whatWasAdded.Contains(current[i]) && previous.Contains(current[i])) - { - contextTable[DeltaTypes.UnChanged].Add(current[i]); - } - } - - } - - public void OnServerListValuesChanged(List> previous, List> current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(List> previous, List> current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new List>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new List>()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new List>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new List>()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionServer.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - - } - - public class ListTestHelperInt : ListTestHelperBase, IListTestHelperBase - { - public static Dictionary> Instances = new Dictionary>(); - - public static void ResetState() - { - Instances.Clear(); - } - - public NetworkVariable> ListCollectionServer = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - // This tracks what has changed per instance which is used to compare to all other instances - public Dictionary>> NetworkVariableChanges = new Dictionary>>(); - - public bool ValidateInstances() - { - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var otherOwnerCollection = Instances[clientId][NetworkObjectId].ListCollectionOwner; - var otherServerCollection = Instances[clientId][NetworkObjectId].ListCollectionServer; - if (!ListCollectionOwner.Value.SequenceEqual(otherOwnerCollection.Value)) - { - return false; - } - if (!ListCollectionServer.Value.SequenceEqual(otherServerCollection.Value)) - { - return false; - } - } - return true; - } - - private bool ChangesMatch(Dictionary> local, Dictionary> other) - { - var deltaTypes = Enum.GetValues(typeof(DeltaTypes)).OfType().ToList(); - foreach (var deltaType in deltaTypes) - { - LogMessage($"Comparing {deltaType}:"); - if (local[deltaType].Count != other[deltaType].Count) - { - LogMessage($"{deltaType}s did not match!"); - return false; - } - - for (int i = 0; i < local[deltaType].Count; i++) - { - if (!local[deltaType][i].Equals(other[deltaType][i])) - { - LogMessage($"Sequence set ({i}) does not match! Local[{i}] = {local[deltaType][i]} Remote[{i}].Count = {other[deltaType][i]}."); - return false; - } - } - } - return true; - } - - public override bool CompareTrackedChanges(Targets target) - { - LogStart(); - var localChanges = NetworkVariableChanges[target]; - foreach (var clientId in NetworkManager.ConnectedClientsIds) - { - if (clientId == NetworkManager.LocalClientId) - { - continue; - } - if (!Instances.ContainsKey(clientId)) - { - return false; - } - if (!Instances[clientId].ContainsKey(NetworkObjectId)) - { - return false; - } - var entry = Instances[clientId][NetworkObjectId]; - var otherChanges = entry.NetworkVariableChanges[target]; - LogMessage($"Comparing against client-{clientId} {entry.name}:"); - if (!ChangesMatch(localChanges, otherChanges)) - { - LogMessage($"Client-{clientId} {entry.name} did not match!"); - return false; - } - LogMessage($"Client-{clientId} {entry.name} matched!"); - } - return true; - } - - private List GetInitialValues() - { - var list = new List(); - for (int i = 0; i < 10; i++) - { - list.Add(Random.Range(0, ushort.MaxValue)); - } - return list; - } - - public NetworkVariable> GetNetVar(Targets target) - { - return target == Targets.Server ? ListCollectionServer : ListCollectionOwner; - } - - public List OnSetServerValues() - { - return GetInitialValues(); - } - - public List OnSetOwnerValues() - { - return GetInitialValues(); - } - - - public void UpdateValue(int value, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - var index = netVar.Value.IndexOf(value); - netVar.Value[index] = value; - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Add(int value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Add(value); - netVar.CheckDirtyState(); - } - - public void AddRange(List values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.AddRange(values); - netVar.CheckDirtyState(); - } - - public void Insert(int value, int index, Targets target, bool checkDirty = true) - { - var netVar = GetNetVar(target); - netVar.Value.Insert(index, value); - if (checkDirty) - { - netVar.CheckDirtyState(); - } - } - - public void Remove(int value, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Remove(value); - netVar.CheckDirtyState(); - } - - public void FullSet(List values, Targets target) - { - var netVar = GetNetVar(target); - netVar.Value = values; - netVar.CheckDirtyState(); - } - - public void Clear(Targets target) - { - var netVar = GetNetVar(target); - netVar.Value.Clear(); - netVar.CheckDirtyState(); - } - - public void TrackChanges(Targets target, List previous, List current) - { - var contextTable = NetworkVariableChanges[target]; - - var whatWasAdded = current.Except(previous).ToList(); - var whatWasRemoved = previous.Where((c) => !current.Contains(c)).ToList(); - var whatWasNeitherAddedOrRemoved = current.Where((c) => previous.Contains(c) && !whatWasAdded.Contains(c)).ToList(); - var whatChanged = whatWasNeitherAddedOrRemoved.Where((c) => previous.Contains(c) && !previous.Where((d) => d.Equals(c)).FirstOrDefault().Equals(c)).ToList(); - var whatRemainedTheSame = whatWasNeitherAddedOrRemoved.Where((c) => !whatChanged.Contains(c)).ToList(); - - contextTable[DeltaTypes.Added] = whatWasAdded; - contextTable[DeltaTypes.Removed] = whatWasRemoved; - contextTable[DeltaTypes.Changed] = whatChanged; - contextTable[DeltaTypes.UnChanged] = whatRemainedTheSame; - } - - public void OnServerListValuesChanged(List previous, List current) - { - TrackChanges(Targets.Server, previous, current); - } - - public void OnOwnerListValuesChanged(List previous, List current) - { - TrackChanges(Targets.Owner, previous, current); - } - - /// - /// Keeps track of each client instsnce releative player instance with this component - /// - private void TrackRelativeInstances() - { - if (!Instances.ContainsKey(NetworkManager.LocalClientId)) - { - Instances.Add(NetworkManager.LocalClientId, new Dictionary()); - } - - if (!Instances[NetworkManager.LocalClientId].ContainsKey(NetworkObjectId)) - { - Instances[NetworkManager.LocalClientId].Add(NetworkObjectId, this); - } - ResetTrackedChanges(); - } - - public void ResetTrackedChanges() - { - NetworkVariableChanges.Clear(); - NetworkVariableChanges.Add(Targets.Owner, new Dictionary>()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Added, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Changed, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.Removed, new List()); - NetworkVariableChanges[Targets.Owner].Add(DeltaTypes.UnChanged, new List()); - NetworkVariableChanges.Add(Targets.Server, new Dictionary>()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Added, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Changed, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.Removed, new List()); - NetworkVariableChanges[Targets.Server].Add(DeltaTypes.UnChanged, new List()); - } - - protected override void OnNetworkPostSpawn() - { - TrackRelativeInstances(); - - ListCollectionServer.OnValueChanged += OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged += OnOwnerListValuesChanged; - - if (IsServer) - { - ListCollectionServer.Value = OnSetServerValues(); - ListCollectionOwner.CheckDirtyState(); - } - - if (IsOwner) - { - ListCollectionOwner.Value = OnSetOwnerValues(); - ListCollectionOwner.CheckDirtyState(); - } - base.OnNetworkPostSpawn(); - } - public override void OnNetworkDespawn() - { - ListCollectionServer.OnValueChanged -= OnServerListValuesChanged; - ListCollectionOwner.OnValueChanged -= OnOwnerListValuesChanged; - base.OnNetworkDespawn(); - } - } - #endregion - - #region BASE TEST COMPONENT HELPERS - public class ListTestHelperBase : NetworkBehaviour - { - protected static bool IsDebugMode { get; private set; } - - public enum Targets - { - Server, - Owner - } - - public enum DeltaTypes - { - Added, - Removed, - Changed, - UnChanged - } - - private StringBuilder m_StringBuilder = new StringBuilder(); - - public string GetLog() - { - return m_StringBuilder.ToString(); - } - - protected void LogMessage(string message) - { - m_StringBuilder.AppendLine(message); - } - - protected void LogStart() - { - m_StringBuilder.Clear(); - m_StringBuilder.AppendLine($"[Client-{NetworkManager.LocalClientId}][{name}] Log Started."); - } - - public void SetDebugMode(bool isDebug) - { - IsDebugMode = isDebug; - } - - public virtual bool CompareTrackedChanges(Targets target) - { - return false; - } - } - - public interface IListTestHelperBase - { - public bool ValidateInstances(); - - public NetworkVariable> GetNetVar(ListTestHelperBase.Targets target); - - public List OnSetServerValues(); - - public List OnSetOwnerValues(); - - public void UpdateValue(T value, ListTestHelperBase.Targets target, bool checkDirty = true); - - public void Add(T value, ListTestHelperBase.Targets target); - - public void AddRange(List values, ListTestHelperBase.Targets target); - - public void Insert(T value, int index, ListTestHelperBase.Targets target, bool checkDirty = true); - - public void Remove(T value, ListTestHelperBase.Targets target); - - public void FullSet(List values, ListTestHelperBase.Targets target); - - public void Clear(ListTestHelperBase.Targets target); - - public void TrackChanges(ListTestHelperBase.Targets target, List previous, List current); - - public void OnServerListValuesChanged(List previous, List current); - - public void OnOwnerListValuesChanged(List previous, List current); - - public void ResetTrackedChanges(); - } - - public interface IDictionaryTestHelperBase - { - public bool ValidateInstances(); - - public NetworkVariable> GetNetVar(ListTestHelperBase.Targets target); - - public Dictionary OnSetServerValues(); - - public Dictionary OnSetOwnerValues(); - - public bool UpdateValue((TKey, TValue) value, ListTestHelperBase.Targets target, bool checkDirty = true); - - public void Add((TKey, TValue) value, ListTestHelperBase.Targets target); - - public void Remove(TKey key, ListTestHelperBase.Targets target); - - public void FullSet(Dictionary values, ListTestHelperBase.Targets target); - - public void Clear(ListTestHelperBase.Targets target); - - public void TrackChanges(ListTestHelperBase.Targets target, Dictionary previous, Dictionary current); - - public void OnServerListValuesChanged(Dictionary previous, Dictionary current); - - public void OnOwnerListValuesChanged(Dictionary previous, Dictionary current); - - public void ResetTrackedChanges(); - } - - public interface IHashSetTestHelperBase - { - public bool ValidateInstances(); - - public NetworkVariable> GetNetVar(ListTestHelperBase.Targets target); - - public HashSet OnSetServerValues(); - - public HashSet OnSetOwnerValues(); - - public void Add(T value, ListTestHelperBase.Targets target); - - public void Remove(T value, ListTestHelperBase.Targets target); - - public void Clear(ListTestHelperBase.Targets target); - - public void TrackChanges(ListTestHelperBase.Targets target, HashSet previous, HashSet current); - - public void OnServerListValuesChanged(HashSet previous, HashSet current); - - public void OnOwnerListValuesChanged(HashSet previous, HashSet current); - - public void ResetTrackedChanges(); - } - #endregion -} diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs.meta deleted file mode 100644 index 32c6910..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 7d01969a8bbbd7146a24490a5190ea7e \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs deleted file mode 100644 index 1a3a6d3..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs +++ /dev/null @@ -1,165 +0,0 @@ -#if !NGO_MINIMALPROJECT -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixtureSource(nameof(TestDataSource))] - internal class NetworkVariableInheritanceTests : NetcodeIntegrationTest - { - public NetworkVariableInheritanceTests(HostOrServer hostOrServer) - : base(hostOrServer) - { - } - - protected override int NumberOfClients => 2; - - public static IEnumerable TestDataSource() => - Enum.GetValues(typeof(HostOrServer)).OfType().Select(x => new TestFixtureData(x)); - - internal class ComponentA : NetworkBehaviour - { - public NetworkVariable PublicFieldA = new NetworkVariable(1); - protected NetworkVariable m_ProtectedFieldA = new NetworkVariable(2); - private NetworkVariable m_PrivateFieldA = new NetworkVariable(3); - - public void ChangeValuesA(int pub, int pro, int pri) - { - PublicFieldA.Value = pub; - m_ProtectedFieldA.Value = pro; - m_PrivateFieldA.Value = pri; - } - - public bool CompareValuesA(ComponentA other) - { - return PublicFieldA.Value == other.PublicFieldA.Value && - m_ProtectedFieldA.Value == other.m_ProtectedFieldA.Value && - m_PrivateFieldA.Value == other.m_PrivateFieldA.Value; - } - } - - internal class ComponentB : ComponentA - { - public NetworkVariable PublicFieldB = new NetworkVariable(11); - protected NetworkVariable m_ProtectedFieldB = new NetworkVariable(22); - private NetworkVariable m_PrivateFieldB = new NetworkVariable(33); - - public void ChangeValuesB(int pub, int pro, int pri) - { - PublicFieldB.Value = pub; - m_ProtectedFieldB.Value = pro; - m_PrivateFieldB.Value = pri; - } - - public bool CompareValuesB(ComponentB other) - { - return PublicFieldB.Value == other.PublicFieldB.Value && - m_ProtectedFieldB.Value == other.m_ProtectedFieldB.Value && - m_PrivateFieldB.Value == other.m_PrivateFieldB.Value; - } - } - - internal class ComponentC : ComponentB - { - public NetworkVariable PublicFieldC = new NetworkVariable(111); - protected NetworkVariable m_ProtectedFieldC = new NetworkVariable(222); - private NetworkVariable m_PrivateFieldC = new NetworkVariable(333); - - public void ChangeValuesC(int pub, int pro, int pri) - { - PublicFieldC.Value = pub; - m_ProtectedFieldA.Value = pro; - m_PrivateFieldC.Value = pri; - } - - public bool CompareValuesC(ComponentC other) - { - return PublicFieldC.Value == other.PublicFieldC.Value && - m_ProtectedFieldC.Value == other.m_ProtectedFieldC.Value && - m_PrivateFieldC.Value == other.m_PrivateFieldC.Value; - } - } - - private GameObject m_TestObjectPrefab; - private ulong m_TestObjectId = 0; - - protected override void OnOneTimeSetup() - { - NetworkVariableBase.IgnoreInitializeWarning = true; - base.OnOneTimeSetup(); - } - - protected override void OnOneTimeTearDown() - { - NetworkVariableBase.IgnoreInitializeWarning = false; - base.OnOneTimeTearDown(); - } - - protected override void OnServerAndClientsCreated() - { - m_TestObjectPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableInheritanceTests)}.{nameof(m_TestObjectPrefab)}]"); - m_TestObjectPrefab.AddComponent(); - m_TestObjectPrefab.AddComponent(); - m_TestObjectPrefab.AddComponent(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - var serverTestObject = SpawnObject(m_TestObjectPrefab, m_ServerNetworkManager).GetComponent(); - m_TestObjectId = serverTestObject.NetworkObjectId; - - var serverTestComponentA = serverTestObject.GetComponent(); - var serverTestComponentB = serverTestObject.GetComponent(); - var serverTestComponentC = serverTestObject.GetComponent(); - - serverTestComponentA.ChangeValuesA(1000, 2000, 3000); - serverTestComponentB.ChangeValuesA(1000, 2000, 3000); - serverTestComponentB.ChangeValuesB(1100, 2200, 3300); - serverTestComponentC.ChangeValuesA(1000, 2000, 3000); - serverTestComponentC.ChangeValuesB(1100, 2200, 3300); - serverTestComponentC.ChangeValuesC(1110, 2220, 3330); - - yield return WaitForTicks(m_ServerNetworkManager, 2); - } - - private bool CheckTestObjectComponentValuesOnAll() - { - var serverTestObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId]; - var serverTestComponentA = serverTestObject.GetComponent(); - var serverTestComponentB = serverTestObject.GetComponent(); - var serverTestComponentC = serverTestObject.GetComponent(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var clientTestObject = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjectId]; - var clientTestComponentA = clientTestObject.GetComponent(); - var clientTestComponentB = clientTestObject.GetComponent(); - var clientTestComponentC = clientTestObject.GetComponent(); - if (!serverTestComponentA.CompareValuesA(clientTestComponentA) || - !serverTestComponentB.CompareValuesA(clientTestComponentB) || - !serverTestComponentB.CompareValuesB(clientTestComponentB) || - !serverTestComponentC.CompareValuesA(clientTestComponentC) || - !serverTestComponentC.CompareValuesB(clientTestComponentC) || - !serverTestComponentC.CompareValuesC(clientTestComponentC)) - { - return false; - } - } - - return true; - } - - [UnityTest] - public IEnumerator TestInheritedFields() - { - yield return WaitForConditionOrTimeOut(CheckTestObjectComponentValuesOnAll); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, nameof(CheckTestObjectComponentValuesOnAll)); - } - } -} -#endif diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs.meta deleted file mode 100644 index 3102d68..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableInheritanceTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 41d4aef8f33a8eb4e87879075f868e66 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs deleted file mode 100644 index 73481fd..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs +++ /dev/null @@ -1,306 +0,0 @@ -#if !NGO_MINIMALPROJECT -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixtureSource(nameof(TestDataSource))] - internal class NetworkVariablePermissionTests : NetcodeIntegrationTest - { - public static IEnumerable TestDataSource() - { - NetworkVariableBase.IgnoreInitializeWarning = true; - foreach (HostOrServer hostOrServer in Enum.GetValues(typeof(HostOrServer))) - { - // DANGO-EXP TODO: Add support for distributed authority mode - if (hostOrServer == HostOrServer.DAHost) - { - continue; - } - yield return new TestFixtureData(hostOrServer); - } - - NetworkVariableBase.IgnoreInitializeWarning = false; - } - - protected override int NumberOfClients => 3; - - public NetworkVariablePermissionTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - private GameObject m_TestObjPrefab; - private ulong m_TestObjId = 0; - - protected override void OnServerAndClientsCreated() - { - m_TestObjPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariablePermissionTests)}.{nameof(m_TestObjPrefab)}]"); - var testComp = m_TestObjPrefab.AddComponent(); - } - - protected override IEnumerator OnServerAndClientsConnected() - { - m_TestObjId = SpawnObject(m_TestObjPrefab, m_ServerNetworkManager).GetComponent().NetworkObjectId; - yield return null; - } - - private IEnumerator WaitForPositionsAreEqual(NetworkVariable netvar, Vector3 expected) - { - yield return WaitForConditionOrTimeOut(() => netvar.Value == expected); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut); - } - - private IEnumerator WaitForOwnerWritableAreEqualOnAll() - { - yield return WaitForConditionOrTimeOut(CheckOwnerWritableAreEqualOnAll); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut); - } - - private bool CheckOwnerWritableAreEqualOnAll() - { - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - if (testObjServer.OwnerClientId != testObjClient.OwnerClientId || - testCompServer.OwnerWritable_Position.Value != testCompClient.OwnerWritable_Position.Value || - testCompServer.OwnerWritable_Position.ReadPerm != testCompClient.OwnerWritable_Position.ReadPerm || - testCompServer.OwnerWritable_Position.WritePerm != testCompClient.OwnerWritable_Position.WritePerm) - { - return false; - } - } - return true; - } - - private IEnumerator WaitForServerWritableAreEqualOnAll() - { - yield return WaitForConditionOrTimeOut(CheckServerWritableAreEqualOnAll); - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut); - } - - private bool CheckServerWritableAreEqualOnAll() - { - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - if (testCompServer.ServerWritable_Position.Value != testCompClient.ServerWritable_Position.Value || - testCompServer.ServerWritable_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm || - testCompServer.ServerWritable_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm) - { - return false; - } - } - return true; - } - - private bool CheckOwnerReadWriteAreEqualOnOwnerAndServer() - { - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - if (testObjServer.OwnerClientId == testObjClient.OwnerClientId && - testCompServer.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value && - testCompServer.OwnerReadWrite_Position.ReadPerm == testCompClient.ServerWritable_Position.ReadPerm && - testCompServer.OwnerReadWrite_Position.WritePerm == testCompClient.ServerWritable_Position.WritePerm) - { - return true; - } - } - return false; - } - - private bool CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(NetVarPermTestComp ownerReadWriteObject) - { - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - if (testObjClient.OwnerClientId != ownerReadWriteObject.OwnerClientId || - ownerReadWriteObject.OwnerReadWrite_Position.Value == testCompClient.ServerWritable_Position.Value || - ownerReadWriteObject.OwnerReadWrite_Position.ReadPerm != testCompClient.ServerWritable_Position.ReadPerm || - ownerReadWriteObject.OwnerReadWrite_Position.WritePerm != testCompClient.ServerWritable_Position.WritePerm) - { - return false; - } - } - return true; - } - - [UnityTest] - public IEnumerator ServerChangesOwnerWritableNetVar() - { - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - - var oldValue = testCompServer.OwnerWritable_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - - testCompServer.OwnerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, newValue); - - yield return WaitForOwnerWritableAreEqualOnAll(); - } - - [UnityTest] - public IEnumerator ServerChangesServerWritableNetVar() - { - yield return WaitForServerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - - var oldValue = testCompServer.ServerWritable_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - - testCompServer.ServerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue); - - yield return WaitForServerWritableAreEqualOnAll(); - } - - [UnityTest] - public IEnumerator ClientChangesOwnerWritableNetVar() - { - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - - int clientManagerIndex = m_ClientNetworkManagers.Length - 1; - var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId; - testObjServer.ChangeOwnership(newOwnerClientId); - yield return WaitForTicks(m_ServerNetworkManager, 2); - - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - - var oldValue = testCompClient.OwnerWritable_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - - testCompClient.OwnerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue); - - yield return WaitForOwnerWritableAreEqualOnAll(); - } - - /// - /// This tests the scenario where a client owner has both read and write - /// permissions set. The server should be the only instance that can read - /// the NetworkVariable. ServerCannotChangeOwnerWritableNetVar performs - /// the same check to make sure the server cannot write to a client owner - /// NetworkVariable with owner write permissions. - /// - [UnityTest] - public IEnumerator ClientOwnerWithReadWriteChangesNetVar() - { - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - - int clientManagerIndex = m_ClientNetworkManagers.Length - 1; - var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId; - testObjServer.ChangeOwnership(newOwnerClientId); - yield return WaitForTicks(m_ServerNetworkManager, 2); - - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - - var oldValue = testCompClient.OwnerReadWrite_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - - testCompClient.OwnerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue); - - // Verify the client owner and server match - yield return CheckOwnerReadWriteAreEqualOnOwnerAndServer(); - - // Verify the non-owner clients do not have the same Value but do have the same permissions - yield return CheckOwnerReadWriteAreNotEqualOnNonOwnerClients(testCompClient); - } - - - [UnityTest] - public IEnumerator ClientCannotChangeServerWritableNetVar() - { - yield return WaitForServerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - - int clientManagerIndex = m_ClientNetworkManagers.Length - 1; - var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId; - testObjServer.ChangeOwnership(newOwnerClientId); - yield return WaitForTicks(m_ServerNetworkManager, 2); - - yield return WaitForServerWritableAreEqualOnAll(); - - var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - - var oldValue = testCompClient.ServerWritable_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - LogAssert.Expect(LogType.Error, testCompClient.ServerWritable_Position.GetWritePermissionError()); - testCompClient.ServerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, oldValue); - - yield return WaitForServerWritableAreEqualOnAll(); - - testCompServer.ServerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompServer.ServerWritable_Position, newValue); - - yield return WaitForServerWritableAreEqualOnAll(); - } - - [UnityTest] - public IEnumerator ServerCannotChangeOwnerWritableNetVar() - { - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompServer = testObjServer.GetComponent(); - - int clientManagerIndex = m_ClientNetworkManagers.Length - 1; - var newOwnerClientId = m_ClientNetworkManagers[clientManagerIndex].LocalClientId; - testObjServer.ChangeOwnership(newOwnerClientId); - yield return WaitForTicks(m_ServerNetworkManager, 4); - - yield return WaitForOwnerWritableAreEqualOnAll(); - - var oldValue = testCompServer.OwnerWritable_Position.Value; - var newValue = oldValue + new Vector3(Random.Range(0, 100.0f), Random.Range(0, 100.0f), Random.Range(0, 100.0f)); - - LogAssert.Expect(LogType.Error, testCompServer.OwnerWritable_Position.GetWritePermissionError()); - testCompServer.OwnerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompServer.OwnerWritable_Position, oldValue); - - yield return WaitForOwnerWritableAreEqualOnAll(); - - var testObjClient = m_ClientNetworkManagers[clientManagerIndex].SpawnManager.SpawnedObjects[m_TestObjId]; - var testCompClient = testObjClient.GetComponent(); - - testCompClient.OwnerWritable_Position.Value = newValue; - yield return WaitForPositionsAreEqual(testCompClient.OwnerWritable_Position, newValue); - - yield return WaitForOwnerWritableAreEqualOnAll(); - } - } -} -#endif diff --git a/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs.meta deleted file mode 100644 index d06c83f..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariablePermissionTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 60d49d322bef8ff4ebb8c4abf57e18e3 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs deleted file mode 100644 index d67d207..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs +++ /dev/null @@ -1,5093 +0,0 @@ -#if !NGO_MINIMALPROJECT -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Random = UnityEngine.Random; - -namespace Unity.Netcode.RuntimeTests -{ - internal struct TestStruct : INetworkSerializable, IEquatable - { - public uint SomeInt; - public bool SomeBool; - public static bool NetworkSerializeCalledOnWrite; - public static bool NetworkSerializeCalledOnRead; - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - if (serializer.IsReader) - { - NetworkSerializeCalledOnRead = true; - } - else - { - NetworkSerializeCalledOnWrite = true; - } - serializer.SerializeValue(ref SomeInt); - serializer.SerializeValue(ref SomeBool); - } - - public bool Equals(TestStruct other) - { - return SomeInt == other.SomeInt && SomeBool == other.SomeBool; - } - - public override bool Equals(object obj) - { - return obj is TestStruct other && Equals(other); - } - - public override int GetHashCode() - { - unchecked - { - return ((int)SomeInt * 397) ^ SomeBool.GetHashCode(); - } - } - } - - internal class TestClass : INetworkSerializable, IEquatable - { - public uint SomeInt; - public bool SomeBool; - public static bool NetworkSerializeCalledOnWrite; - public static bool NetworkSerializeCalledOnRead; - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - if (serializer.IsReader) - { - NetworkSerializeCalledOnRead = true; - } - else - { - NetworkSerializeCalledOnWrite = true; - } - serializer.SerializeValue(ref SomeInt); - serializer.SerializeValue(ref SomeBool); - } - - public bool Equals(TestClass other) - { - return SomeInt == other.SomeInt && SomeBool == other.SomeBool; - } - - public override bool Equals(object obj) - { - return obj is TestClass other && Equals(other); - } - - public override int GetHashCode() - { - unchecked - { - return ((int)SomeInt * 397) ^ SomeBool.GetHashCode(); - } - } - } - - // Used just to create a NetworkVariable in the templated NetworkBehaviour type that isn't referenced anywhere else - // Please do not reference this class anywhere else! - internal class TestClass_ReferencedOnlyByTemplateNetworkBehaviourType : TestClass, IEquatable - { - public bool Equals(TestClass_ReferencedOnlyByTemplateNetworkBehaviourType other) - { - return Equals((TestClass)other); - } - } - - internal class NetworkVariableTest : NetworkBehaviour - { - public enum SomeEnum - { - A, - B, - C - } - public readonly NetworkVariable TheScalar = new NetworkVariable(); - public readonly NetworkVariable TheEnum = new NetworkVariable(); - public readonly NetworkList TheList = new NetworkList(); - public readonly NetworkList TheStructList = new NetworkList(); - public readonly NetworkList TheLargeList = new NetworkList(); - - public readonly NetworkVariable FixedString32 = new NetworkVariable(); - - private void ListChanged(NetworkListEvent e) - { - ListDelegateTriggered = true; - } - - public void Awake() - { - TheList.OnListChanged += ListChanged; - } - - public readonly NetworkVariable TheStruct = new NetworkVariable(); - public readonly NetworkVariable TheClass = new NetworkVariable(); - - public NetworkVariable> TheTemplateStruct = new NetworkVariable>(); - public NetworkVariable> TheTemplateClass = new NetworkVariable>(); - - public bool ListDelegateTriggered; - - public override void OnNetworkSpawn() - { - if (!IsServer) - { - NetworkVariableTests.ClientNetworkVariableTestSpawned(this); - } - base.OnNetworkSpawn(); - } - } - - /// - /// Handles the more generic conditional logic for NetworkList tests - /// which can be used with the - /// that accepts anything derived from the class - /// as a parameter. - /// - internal class NetworkListTestPredicate : ConditionalPredicateBase - { - private const int k_MaxRandomValue = 1000; - - private Dictionary> m_StateFunctions; - - // Player1 component on the Server - private NetworkVariableTest m_Player1OnServer; - - // Player1 component on client1 - private NetworkVariableTest m_Player1OnClient1; - - private string m_TestStageFailedMessage; - - public enum NetworkListTestStates - { - Add, - ContainsLarge, - Contains, - VerifyData, - IndexOf, - } - - private NetworkListTestStates m_NetworkListTestState; - - public void SetNetworkListTestState(NetworkListTestStates networkListTestState) - { - m_NetworkListTestState = networkListTestState; - } - - /// - /// Determines if the condition has been reached for the current NetworkListTestState - /// - protected override bool OnHasConditionBeenReached() - { - var isStateRegistered = m_StateFunctions.ContainsKey(m_NetworkListTestState); - Assert.IsTrue(isStateRegistered); - return m_StateFunctions[m_NetworkListTestState].Invoke(); - } - - /// - /// Provides all information about the players for both sides for simplicity and informative sake. - /// - /// - private string ConditionFailedInfo() - { - return $"{m_NetworkListTestState} condition test failed:\n Server List Count: {m_Player1OnServer.TheList.Count} vs Client List Count: {m_Player1OnClient1.TheList.Count}\n" + - $"Server List Count: {m_Player1OnServer.TheLargeList.Count} vs Client List Count: {m_Player1OnClient1.TheLargeList.Count}\n" + - $"Server Delegate Triggered: {m_Player1OnServer.ListDelegateTriggered} | Client Delegate Triggered: {m_Player1OnClient1.ListDelegateTriggered}\n"; - } - - /// - /// When finished, check if a time out occurred and if so assert and provide meaningful information to troubleshoot why - /// - protected override void OnFinished() - { - Assert.IsFalse(TimedOut, $"{nameof(NetworkListTestPredicate)} timed out waiting for the {m_NetworkListTestState} condition to be reached! \n" + ConditionFailedInfo()); - } - - // Uses the ArrayOperator and validates that on both sides the count and values are the same - private bool OnVerifyData() - { - // Wait until both sides have the same number of elements - if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count) - { - return false; - } - - // Check the client values against the server values to make sure they match - for (int i = 0; i < m_Player1OnServer.TheList.Count; i++) - { - if (m_Player1OnServer.TheList[i] != m_Player1OnClient1.TheList[i]) - { - return false; - } - } - return true; - } - - /// - /// Verifies the data count, values, and that the ListDelegate on both sides was triggered - /// - private bool OnAdd() - { - bool wasTriggerred = m_Player1OnServer.ListDelegateTriggered && m_Player1OnClient1.ListDelegateTriggered; - return wasTriggerred && OnVerifyData(); - } - - /// - /// The current version of this test only verified the count of the large list, so that is what this does - /// - private bool OnContainsLarge() - { - return m_Player1OnServer.TheLargeList.Count == m_Player1OnClient1.TheLargeList.Count; - } - - /// - /// Tests NetworkList.Contains which also verifies all values are the same on both sides - /// - private bool OnContains() - { - // Wait until both sides have the same number of elements - if (m_Player1OnServer.TheList.Count != m_Player1OnClient1.TheList.Count) - { - return false; - } - - // Parse through all server values and use the NetworkList.Contains method to check if the value is in the list on the client side - foreach (var serverValue in m_Player1OnServer.TheList) - { - if (!m_Player1OnClient1.TheList.Contains(serverValue)) - { - return false; - } - } - return true; - } - - /// - /// Tests NetworkList.IndexOf and verifies that all values are aligned on both sides - /// - private bool OnIndexOf() - { - foreach (var serverSideValue in m_Player1OnServer.TheList) - { - var indexToTest = m_Player1OnServer.TheList.IndexOf(serverSideValue); - if (indexToTest != m_Player1OnServer.TheList.IndexOf(serverSideValue)) - { - return false; - } - } - return true; - } - - public NetworkListTestPredicate(NetworkVariableTest player1OnServer, NetworkVariableTest player1OnClient1, NetworkListTestStates networkListTestState, int elementCount) - { - m_NetworkListTestState = networkListTestState; - m_Player1OnServer = player1OnServer; - m_Player1OnClient1 = player1OnClient1; - m_StateFunctions = new Dictionary> - { - { NetworkListTestStates.Add, OnAdd }, - { NetworkListTestStates.ContainsLarge, OnContainsLarge }, - { NetworkListTestStates.Contains, OnContains }, - { NetworkListTestStates.VerifyData, OnVerifyData }, - { NetworkListTestStates.IndexOf, OnIndexOf } - }; - - if (networkListTestState == NetworkListTestStates.ContainsLarge) - { - for (var i = 0; i < elementCount; ++i) - { - m_Player1OnServer.TheLargeList.Add(new FixedString128Bytes()); - } - } - else - { - for (int i = 0; i < elementCount; i++) - { - m_Player1OnServer.TheList.Add(Random.Range(0, k_MaxRandomValue)); - } - } - } - } - - internal class NetvarDespawnShutdown : NetworkBehaviour - { - private NetworkVariable m_IntNetworkVariable = new NetworkVariable(); - private NetworkList m_IntList; - - private void Awake() - { - m_IntList = new NetworkList(); - } - - public override void OnNetworkDespawn() - { - if (IsServer) - { - m_IntNetworkVariable.Value = 5; - for (int i = 0; i < 10; i++) - { - m_IntList.Add(i); - } - } - base.OnNetworkDespawn(); - } - } - - /// - /// Validates that setting values for NetworkVariable or NetworkList during the - /// OnNetworkDespawn method will not cause an exception to occur. - /// - internal class NetworkVariableModifyOnNetworkDespawn : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - private GameObject m_TestPrefab; - - protected override void OnOneTimeSetup() - { - NetworkVariableBase.IgnoreInitializeWarning = true; - base.OnOneTimeSetup(); - } - - protected override void OnOneTimeTearDown() - { - NetworkVariableBase.IgnoreInitializeWarning = false; - base.OnOneTimeTearDown(); - } - - protected override void OnServerAndClientsCreated() - { - m_TestPrefab = CreateNetworkObjectPrefab("NetVarDespawn"); - m_TestPrefab.AddComponent(); - base.OnServerAndClientsCreated(); - } - - private bool OnClientSpawnedTestPrefab(ulong networkObjectId) - { - var clientId = m_ClientNetworkManagers[0].LocalClientId; - if (!s_GlobalNetworkObjects.ContainsKey(clientId)) - { - return false; - } - - if (!s_GlobalNetworkObjects[clientId].ContainsKey(networkObjectId)) - { - return false; - } - - return true; - } - - [UnityTest] - public IEnumerator ModifyNetworkVariableOrListOnNetworkDespawn() - { - var instance = SpawnObject(m_TestPrefab, m_ServerNetworkManager); - yield return WaitForConditionOrTimeOut(() => OnClientSpawnedTestPrefab(instance.GetComponent().NetworkObjectId)); - m_ServerNetworkManager.Shutdown(); - // As long as no excetptions occur, the test passes. - } - } - -#if !MULTIPLAYER_TOOLS - [TestFixture(true)] -#endif - [TestFixture(false)] - internal class NetworkVariableTests : NetcodeIntegrationTest - { - private const string k_StringTestValue = "abcdefghijklmnopqrstuvwxyz"; - private static readonly FixedString32Bytes k_FixedStringTestValue = k_StringTestValue; - protected override int NumberOfClients => 2; - - private const uint k_TestUInt = 0x12345678; - - private const int k_TestVal1 = 111; - private const int k_TestVal2 = 222; - private const int k_TestVal3 = 333; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - private static List s_ClientNetworkVariableTestInstances = new List(); - public static void ClientNetworkVariableTestSpawned(NetworkVariableTest networkVariableTest) - { - s_ClientNetworkVariableTestInstances.Add(networkVariableTest); - } - - // Player1 component on the server - private NetworkVariableTest m_Player1OnServer; - - // Player1 component on client1 - private NetworkVariableTest m_Player1OnClient1; - - private NetworkListTestPredicate m_NetworkListPredicateHandler; - - private readonly bool m_EnsureLengthSafety; - - public NetworkVariableTests(bool ensureLengthSafety) - { - m_EnsureLengthSafety = ensureLengthSafety; - } - - protected override bool CanStartServerAndClients() - { - return false; - } - - protected override void OnOneTimeSetup() - { - NetworkVariableBase.IgnoreInitializeWarning = true; - base.OnOneTimeSetup(); - } - - protected override void OnOneTimeTearDown() - { - NetworkVariableBase.IgnoreInitializeWarning = false; - base.OnOneTimeTearDown(); - } - - /// - /// This is an adjustment to how the server and clients are started in order - /// to avoid timing issues when running in a stand alone test runner build. - /// - private void InitializeServerAndClients(HostOrServer useHost) - { - s_ClientNetworkVariableTestInstances.Clear(); - m_PlayerPrefab.AddComponent(); - - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - - m_ServerNetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_EnsureLengthSafety; - m_ServerNetworkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab; - foreach (var client in m_ClientNetworkManagers) - { - client.NetworkConfig.EnsureNetworkVariableLengthSafety = m_EnsureLengthSafety; - client.NetworkConfig.PlayerPrefab = m_PlayerPrefab; - } - - Assert.True(NetcodeIntegrationTestHelpers.Start(useHost == HostOrServer.Host, m_ServerNetworkManager, m_ClientNetworkManagers), "Failed to start server and client instances"); - - RegisterSceneManagerHandler(); - - // Wait for connection on client and server side - var success = WaitForClientsConnectedOrTimeOutWithTimeTravel(); - Assert.True(success, $"Timed-out waiting for all clients to connect!"); - - // These are the *SERVER VERSIONS* of the *CLIENT PLAYER 1 & 2* - var result = new NetcodeIntegrationTestHelpers.ResultWrapper(); - - NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentationWithTimeTravel( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ServerNetworkManager, result); - - // Assign server-side client's player - m_Player1OnServer = result.Result.GetComponent(); - - // This is client1's view of itself - NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentationWithTimeTravel( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ClientNetworkManagers[0], result); - - // Assign client-side local player - m_Player1OnClient1 = result.Result.GetComponent(); - - m_Player1OnServer.TheList.Clear(); - - if (m_Player1OnServer.TheList.Count > 0) - { - throw new Exception("at least one server network container not empty at start"); - } - if (m_Player1OnClient1.TheList.Count > 0) - { - throw new Exception("at least one client network container not empty at start"); - } - - var instanceCount = useHost == HostOrServer.Host ? NumberOfClients * 3 : NumberOfClients * 2; - // Wait for the client-side to notify it is finished initializing and spawning. - success = WaitForConditionOrTimeOutWithTimeTravel(() => s_ClientNetworkVariableTestInstances.Count == instanceCount); - - Assert.True(success, "Timed out waiting for all client NetworkVariableTest instances to register they have spawned!"); - - TimeTravelToNextTick(); - } - -#if !MULTIPLAYER_TOOLS - /// - /// Runs generalized tests on all predefined NetworkVariable types - /// - [Test] - public void AllNetworkVariableTypes([Values] HostOrServer useHost) - { - // Create, instantiate, and host - // This would normally go in Setup, but since every other test but this one - // uses NetworkManagerHelper, and it does its own NetworkManager setup / teardown, - // for now we put this within this one test until we migrate it to MIH - Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out NetworkManager server, useHost == HostOrServer.Host ? NetworkManagerHelper.NetworkManagerOperatingMode.Host : NetworkManagerHelper.NetworkManagerOperatingMode.Server)); - - Assert.IsTrue(server.IsHost == (useHost == HostOrServer.Host), $"{nameof(useHost)} does not match the server.IsHost value!"); - - Guid gameObjectId = NetworkManagerHelper.AddGameNetworkObject("NetworkVariableTestComponent"); - - var networkVariableTestComponent = NetworkManagerHelper.AddComponentToObject(gameObjectId); - - NetworkManagerHelper.SpawnNetworkObject(gameObjectId); - - // Start Testing - networkVariableTestComponent.EnableTesting = true; - - var success = WaitForConditionOrTimeOutWithTimeTravel(() => true == networkVariableTestComponent.IsTestComplete()); - Assert.True(success, "Timed out waiting for the test to complete!"); - - // Stop Testing - networkVariableTestComponent.EnableTesting = false; - - Assert.IsTrue(networkVariableTestComponent.DidAllValuesChange()); - networkVariableTestComponent.AssertAllValuesAreCorrect(); - - // Disable this once we are done. - networkVariableTestComponent.gameObject.SetActive(false); - - // This would normally go in Teardown, but since every other test but this one - // uses NetworkManagerHelper, and it does its own NetworkManager setup / teardown, - // for now we put this within this one test until we migrate it to MIH - NetworkManagerHelper.ShutdownNetworkManager(); - } - - [Test] - public void ClientWritePermissionTest([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - // client must not be allowed to write to a server auth variable - - LogAssert.Expect(LogType.Error, m_Player1OnClient1.TheScalar.GetWritePermissionError()); - m_Player1OnClient1.TheScalar.Value = k_TestVal1; - } - - /// - /// Runs tests that network variables sync on client whatever the local value of . - /// - [Test] - public void NetworkVariableSync_WithDifferentTimeScale([Values] HostOrServer useHost, [Values(0.0f, 1.0f, 2.0f)] float timeScale) - { - Time.timeScale = timeScale; - - InitializeServerAndClients(useHost); - - m_Player1OnServer.TheScalar.Value = k_TestVal1; - - // Now wait for the client side version to be updated to k_TestVal1 - var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_Player1OnClient1.TheScalar.Value == k_TestVal1); - Assert.True(success, "Timed out waiting for client-side NetworkVariable to update!"); - } - - [Test] - public void FixedString32Test([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - m_Player1OnServer.FixedString32.Value = k_FixedStringTestValue; - - // Now wait for the client side version to be updated to k_FixedStringTestValue - var success = WaitForConditionOrTimeOutWithTimeTravel(() => m_Player1OnClient1.FixedString32.Value == k_FixedStringTestValue); - Assert.True(success, "Timed out waiting for client-side NetworkVariable to update!"); - } - - [Test] - public void NetworkListAdd([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.Add, 10); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - [Test] - public void WhenListContainsManyLargeValues_OverflowExceptionIsNotThrown([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.ContainsLarge, 20); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - [Test] - public void NetworkListContains([Values] HostOrServer useHost) - { - // Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated - NetworkListAdd(useHost); - - // Now test the NetworkList.Contains method - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.Contains); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - - [Test] - public void NetworkListInsert([Values] HostOrServer useHost) - { - // Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated - NetworkListAdd(useHost); - - // Now randomly insert a random value entry - m_Player1OnServer.TheList.Insert(Random.Range(0, 9), Random.Range(1, 99)); - - // Verify the element count and values on the client matches the server - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - [Test] - public void NetworkListIndexOf([Values] HostOrServer useHost) - { - // Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated - NetworkListAdd(useHost); - - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.IndexOf); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - [Test] - public void NetworkListValueUpdate([Values] HostOrServer useHost) - { - var testSucceeded = false; - InitializeServerAndClients(useHost); - // Add 1 element value and verify it is the same on the client - m_NetworkListPredicateHandler = new NetworkListTestPredicate(m_Player1OnServer, m_Player1OnClient1, NetworkListTestPredicate.NetworkListTestStates.Add, 1); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - - // Setup our original and - var previousValue = m_Player1OnServer.TheList[0]; - var updatedValue = previousValue + 10; - - // Callback that verifies the changed event occurred and that the original and new values are correct - void TestValueUpdatedCallback(NetworkListEvent changedEvent) - { - testSucceeded = changedEvent.PreviousValue == previousValue && - changedEvent.Value == updatedValue; - } - - // Subscribe to the OnListChanged event on the client side and - m_Player1OnClient1.TheList.OnListChanged += TestValueUpdatedCallback; - m_Player1OnServer.TheList[0] = updatedValue; - - // Wait until we know the client side matches the server side before checking if the callback was a success - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData); - WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler); - - Assert.That(testSucceeded); - m_Player1OnClient1.TheList.OnListChanged -= TestValueUpdatedCallback; - } - - private List m_ExpectedValuesServer = new List(); - private List m_ExpectedValuesClient = new List(); - - public enum ListRemoveTypes - { - Remove, - RemoveAt - } - - - [Test] - public void NetworkListRemoveTests([Values] HostOrServer useHost, [Values] ListRemoveTypes listRemoveType) - { - m_ExpectedValuesServer.Clear(); - m_ExpectedValuesClient.Clear(); - // Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated - NetworkListAdd(useHost); - - // Randomly remove a few entries - m_Player1OnServer.TheList.OnListChanged += Server_OnListChanged; - m_Player1OnClient1.TheList.OnListChanged += Client_OnListChanged; - - // Remove half of the elements - for (int i = 0; i < (int)(m_Player1OnServer.TheList.Count * 0.5f); i++) - { - var index = Random.Range(0, m_Player1OnServer.TheList.Count - 1); - var value = m_Player1OnServer.TheList[index]; - m_ExpectedValuesServer.Add(value); - m_ExpectedValuesClient.Add(value); - - if (listRemoveType == ListRemoveTypes.RemoveAt) - { - m_Player1OnServer.TheList.RemoveAt(index); - } - else - { - m_Player1OnServer.TheList.Remove(value); - } - } - - // Verify the element count and values on the client matches the server - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - - Assert.True(m_ExpectedValuesServer.Count == 0, $"Server was not notified of all elements removed and still has {m_ExpectedValuesServer.Count} elements left!"); - Assert.True(m_ExpectedValuesClient.Count == 0, $"Client was not notified of all elements removed and still has {m_ExpectedValuesClient.Count} elements left!"); - } - - private void Server_OnListChanged(NetworkListEvent changeEvent) - { - Assert.True(m_ExpectedValuesServer.Contains(changeEvent.Value)); - m_ExpectedValuesServer.Remove(changeEvent.Value); - } - - private void Client_OnListChanged(NetworkListEvent changeEvent) - { - Assert.True(m_ExpectedValuesClient.Contains(changeEvent.Value)); - m_ExpectedValuesClient.Remove(changeEvent.Value); - } - - [Test] - public void NetworkListClear([Values] HostOrServer useHost) - { - // Re-use the NetworkListAdd to initialize the server and client as well as make sure the list is populated - NetworkListAdd(useHost); - m_Player1OnServer.TheList.Clear(); - // Verify the element count and values on the client matches the server - m_NetworkListPredicateHandler.SetNetworkListTestState(NetworkListTestPredicate.NetworkListTestStates.VerifyData); - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(m_NetworkListPredicateHandler)); - } - - [Test] - public void TestNetworkVariableClass([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyClass() - { - return m_Player1OnClient1.TheClass.Value != null && - m_Player1OnClient1.TheClass.Value.SomeBool == m_Player1OnServer.TheClass.Value.SomeBool && - m_Player1OnClient1.TheClass.Value.SomeInt == m_Player1OnServer.TheClass.Value.SomeInt; - } - - m_Player1OnServer.TheClass.Value = new TestClass { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.TheClass.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyClass)); - } - - [Test] - public void TestNetworkVariableTemplateClass([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyClass() - { - return m_Player1OnClient1.TheTemplateClass.Value.Value != null && m_Player1OnClient1.TheTemplateClass.Value.Value.SomeBool == m_Player1OnServer.TheTemplateClass.Value.Value.SomeBool && - m_Player1OnClient1.TheTemplateClass.Value.Value.SomeInt == m_Player1OnServer.TheTemplateClass.Value.Value.SomeInt; - } - - m_Player1OnServer.TheTemplateClass.Value = new ManagedTemplateNetworkSerializableType { Value = new TestClass { SomeInt = k_TestUInt, SomeBool = false } }; - m_Player1OnServer.TheTemplateClass.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyClass)); - } - - [Test] - public void TestNetworkListStruct([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyList() - { - return m_Player1OnClient1.TheStructList.Count == m_Player1OnServer.TheStructList.Count && - m_Player1OnClient1.TheStructList[0].Value == m_Player1OnServer.TheStructList[0].Value && - m_Player1OnClient1.TheStructList[1].Value == m_Player1OnServer.TheStructList[1].Value; - } - - m_Player1OnServer.TheStructList.Add(new StructUsedOnlyInNetworkList { Value = 1 }); - m_Player1OnServer.TheStructList.Add(new StructUsedOnlyInNetworkList { Value = 2 }); - m_Player1OnServer.TheStructList.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyList)); - } - - [Test] - public void TestNetworkVariableStruct([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyStructure() - { - return m_Player1OnClient1.TheStruct.Value.SomeBool == m_Player1OnServer.TheStruct.Value.SomeBool && - m_Player1OnClient1.TheStruct.Value.SomeInt == m_Player1OnServer.TheStruct.Value.SomeInt; - } - - m_Player1OnServer.TheStruct.Value = new TestStruct { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.TheStruct.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyStructure)); - } - - [Test] - public void TestNetworkVariableTemplateStruct([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyStructure() - { - return m_Player1OnClient1.TheTemplateStruct.Value.Value.SomeBool == m_Player1OnServer.TheTemplateStruct.Value.Value.SomeBool && - m_Player1OnClient1.TheTemplateStruct.Value.Value.SomeInt == m_Player1OnServer.TheTemplateStruct.Value.Value.SomeInt; - } - - m_Player1OnServer.TheTemplateStruct.Value = new UnmanagedTemplateNetworkSerializableType { Value = new TestStruct { SomeInt = k_TestUInt, SomeBool = false } }; - m_Player1OnServer.TheTemplateStruct.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyStructure)); - } - - [Test] - public void TestNetworkVariableTemplateBehaviourClass([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyClass() - { - return (m_Player1OnClient1.GetComponent().TheVar.Value != null && m_Player1OnClient1.GetComponent().TheVar.Value.SomeBool == m_Player1OnServer.GetComponent().TheVar.Value.SomeBool && - m_Player1OnClient1.GetComponent().TheVar.Value.SomeInt == m_Player1OnServer.GetComponent().TheVar.Value.SomeInt) - && (m_Player1OnClient1.GetComponent().TheVar2.Value != null && m_Player1OnClient1.GetComponent().TheVar2.Value.SomeBool == m_Player1OnServer.GetComponent().TheVar2.Value.SomeBool && - m_Player1OnClient1.GetComponent().TheVar2.Value.SomeInt == m_Player1OnServer.GetComponent().TheVar2.Value.SomeInt); - } - - m_Player1OnServer.GetComponent().TheVar.Value = new TestClass { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.GetComponent().TheVar2.Value = new TestClass { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.GetComponent().TheVar.SetDirty(true); - m_Player1OnServer.GetComponent().TheVar2.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyClass)); - } - - [Test] - public void TestNetworkVariableTemplateBehaviourClassNotReferencedElsewhere([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyClass() - { - return m_Player1OnClient1.GetComponent().TheVar.Value != null && m_Player1OnClient1.GetComponent().TheVar.Value.SomeBool == m_Player1OnServer.GetComponent().TheVar.Value.SomeBool && - m_Player1OnClient1.GetComponent().TheVar.Value.SomeInt == m_Player1OnServer.GetComponent().TheVar.Value.SomeInt; - } - - m_Player1OnServer.GetComponent().TheVar.Value = new TestClass_ReferencedOnlyByTemplateNetworkBehaviourType { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.GetComponent().TheVar.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyClass)); - } - - [Test] - public void TestNetworkVariableTemplateBehaviourStruct([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyClass() - { - return m_Player1OnClient1.GetComponent().TheVar.Value.SomeBool == m_Player1OnServer.GetComponent().TheVar.Value.SomeBool && - m_Player1OnClient1.GetComponent().TheVar.Value.SomeInt == m_Player1OnServer.GetComponent().TheVar.Value.SomeInt; - } - - m_Player1OnServer.GetComponent().TheVar.Value = new TestStruct { SomeInt = k_TestUInt, SomeBool = false }; - m_Player1OnServer.GetComponent().TheVar.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyClass)); - } - - [Test] - public void TestNetworkVariableEnum([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - - bool VerifyStructure() - { - return m_Player1OnClient1.TheEnum.Value == NetworkVariableTest.SomeEnum.C; - } - - m_Player1OnServer.TheEnum.Value = NetworkVariableTest.SomeEnum.C; - m_Player1OnServer.TheEnum.SetDirty(true); - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyStructure)); - } - - [Test] - public void TestINetworkSerializableClassCallsNetworkSerialize([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - TestClass.NetworkSerializeCalledOnWrite = false; - TestClass.NetworkSerializeCalledOnRead = false; - m_Player1OnServer.TheClass.Value = new TestClass - { - SomeBool = true, - SomeInt = 32 - }; - - static bool VerifyCallback() => TestClass.NetworkSerializeCalledOnWrite && TestClass.NetworkSerializeCalledOnRead; - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyCallback)); - } -#endif - - [Test] - public void TestINetworkSerializableStructCallsNetworkSerialize([Values] HostOrServer useHost) - { - InitializeServerAndClients(useHost); - TestStruct.NetworkSerializeCalledOnWrite = false; - TestStruct.NetworkSerializeCalledOnRead = false; - m_Player1OnServer.TheStruct.Value = new TestStruct() { SomeInt = k_TestUInt, SomeBool = false }; - - static bool VerifyCallback() => TestStruct.NetworkSerializeCalledOnWrite && TestStruct.NetworkSerializeCalledOnRead; - - // Wait for the client-side to notify it is finished initializing and spawning. - Assert.True(WaitForConditionOrTimeOutWithTimeTravel(VerifyCallback)); - } - - [Test] - public void TestCustomGenericSerialization() - { - // Just verifies that the ILPP codegen initialized these values for this type. - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedTypeSerializer), NetworkVariableSerialization.Serializer.GetType()); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization.AreEqual); - - // Verify no issues with generic values... - - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.AreEqual(typeof(UnmanagedArraySerializer), NetworkVariableSerialization>.Serializer.GetType()); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - Assert.IsNotNull(NetworkVariableSerialization>.AreEqual); - } - - [Test] - public void TestUnsupportedManagedTypesThrowExceptions() - { - var variable = new NetworkVariable(); - using var writer = new FastBufferWriter(1024, Allocator.Temp); - using var reader = new FastBufferReader(writer, Allocator.None); - // Just making sure these are null, just in case. - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - Assert.Throws(() => - { - variable.WriteField(writer); - }); - Assert.Throws(() => - { - variable.ReadField(reader); - }); - } - - [Test] - // Exceptions should be thrown in DA mode with UserNetworkVariableSerialization - public void TestUnsupportedManagedTypesWithUserSerializationDoNotThrowExceptionsInClientServerMode() - { - var variable = new NetworkVariable(); - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out string value) => - { - reader.ReadValueSafe(out value); - }; - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in string value) => - { - writer.WriteValueSafe(value); - }; - UserNetworkVariableSerialization.DuplicateValue = (in string a, ref string b) => - { - b = string.Copy(a); - }; - try - { - using var writer = new FastBufferWriter(1024, Allocator.Temp); - variable.Value = "012345"; - variable.WriteField(writer); - variable.Value = ""; - - using var reader = new FastBufferReader(writer, Allocator.None); - variable.ReadField(reader); - Assert.AreEqual("012345", variable.Value); - } - catch (Exception) - { - Assert.True(NetworkVariableSerialization>.IsDistributedAuthority); - } - finally - { - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - } - } - - [Test] - public void TestUnsupportedUnmanagedTypesThrowExceptions() - { - var variable = new NetworkVariable(); - using var writer = new FastBufferWriter(1024, Allocator.Temp); - using var reader = new FastBufferReader(writer, Allocator.None); - // Just making sure these are null, just in case. - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - Assert.Throws(() => - { - variable.WriteField(writer); - }); - Assert.Throws(() => - { - variable.ReadField(reader); - }); - } - - [Test] - public void TestTypesReferencedInSubclassSerializeSuccessfully() - { - var variable = new NetworkVariableSubclass>(); - using var writer = new FastBufferWriter(1024, Allocator.Temp); - var value = new TemplatedValueOnlyReferencedByNetworkVariableSubclass { Value = 12345 }; - variable.Value = value; - variable.WriteField(writer); - variable.Value = new TemplatedValueOnlyReferencedByNetworkVariableSubclass { Value = 54321 }; - - using var reader = new FastBufferReader(writer, Allocator.None); - variable.ReadField(reader); - Assert.AreEqual(value.Value, variable.Value.Value); - } - - [Test] - public void TestUnsupportedUnmanagedTypesWithUserSerializationDoNotThrowExceptions() - { - var variable = new NetworkVariable(); - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out Guid value) => - { - var tmpValue = new ForceNetworkSerializeByMemcpy(); - reader.ReadValueSafe(out tmpValue); - value = tmpValue.Value; - }; - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in Guid value) => - { - var tmpValue = new ForceNetworkSerializeByMemcpy(value); - writer.WriteValueSafe(tmpValue); - }; - UserNetworkVariableSerialization.DuplicateValue = (in Guid a, ref Guid b) => - { - b = a; - }; - try - { - using var writer = new FastBufferWriter(1024, Allocator.Temp); - var guid = Guid.NewGuid(); - variable.Value = guid; - variable.WriteField(writer); - variable.Value = Guid.Empty; - - using var reader = new FastBufferReader(writer, Allocator.None); - variable.ReadField(reader); - Assert.AreEqual(guid, variable.Value); - } - finally - { - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - } - } - [Test] - public void WhenCreatingAnArrayOfNetVars_InitializingVariablesDoesNotThrowAnException() - { - var testObjPrefab = CreateNetworkObjectPrefab($"NetVarArrayPrefab"); - var testComp = testObjPrefab.AddComponent(); - testComp.InitializeVariables(); - - // Verify all variables were initialized - Assert.AreEqual(testComp.InitializedFieldCount, 5); - - Assert.NotNull(testComp.Int0.GetBehaviour()); - Assert.NotNull(testComp.Int1.GetBehaviour()); - Assert.NotNull(testComp.Int2.GetBehaviour()); - Assert.NotNull(testComp.Int3.GetBehaviour()); - Assert.NotNull(testComp.Int4.GetBehaviour()); - - Assert.NotNull(testComp.Int0.Name); - Assert.NotNull(testComp.Int1.Name); - Assert.NotNull(testComp.Int2.Name); - Assert.NotNull(testComp.Int3.Name); - Assert.NotNull(testComp.Int4.Name); - - Assert.AreNotEqual("", testComp.Int0.Name); - Assert.AreNotEqual("", testComp.Int1.Name); - Assert.AreNotEqual("", testComp.Int2.Name); - Assert.AreNotEqual("", testComp.Int3.Name); - Assert.AreNotEqual("", testComp.Int4.Name); - - Assert.AreSame(testComp.AllInts[0], testComp.Int0); - Assert.AreSame(testComp.AllInts[1], testComp.Int1); - Assert.AreSame(testComp.AllInts[2], testComp.Int2); - Assert.AreSame(testComp.AllInts[3], testComp.Int3); - Assert.AreSame(testComp.AllInts[4], testComp.Int4); - } - - private void TestValueType(T testValue, T changedValue) where T : unmanaged - { - var serverVariable = new NetworkVariable(testValue); - var clientVariable = new NetworkVariable(); - using var writer = new FastBufferWriter(1024, Allocator.Temp); - serverVariable.WriteField(writer); - - Assert.IsFalse(NetworkVariableSerialization.AreEqual(ref serverVariable.RefValue(), ref clientVariable.RefValue())); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref serverVariable.RefValue(), ref clientVariable.RefValue())); - - serverVariable.Value = changedValue; - Assert.IsFalse(NetworkVariableSerialization.AreEqual(ref serverVariable.RefValue(), ref clientVariable.RefValue())); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - Assert.IsFalse(NetworkVariableSerialization.AreEqual(ref serverVariable.RefValue(), ref clientVariable.RefValue())); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref serverVariable.RefValue(), ref clientVariable.RefValue())); - } - - public void AssertArraysMatch(ref NativeArray a, ref NativeArray b) where T : unmanaged - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists do not match: {ArrayStr(a)} != {ArrayStr(b)}"); - } - public void AssertArraysDoNotMatch(ref NativeArray a, ref NativeArray b) where T : unmanaged - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists match when they should not: {ArrayStr(a)} == {ArrayStr(b)}"); - } - - private void TestValueTypeNativeArray(NativeArray testValue, NativeArray changedValue) where T : unmanaged - { - VerboseDebug($"Changing {ArrayStr(testValue)} to {ArrayStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var clientVariable = new NetworkVariable>(new NativeArray(1, Allocator.Persistent)); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertArraysDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertArraysMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - - serverVariable.ResetDirty(); - serverVariable.Value.Dispose(); - serverVariable.Value = changedValue; - AssertArraysDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertArraysDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertArraysMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - var cachedValue = changedValue[0]; - var differentValue = changedValue[0]; - foreach (var checkValue in testValue) - { - var checkValueRef = checkValue; - if (!NetworkVariableSerialization.AreEqual(ref checkValueRef, ref differentValue)) - { - differentValue = checkValue; - break; - } - } - changedValue[0] = differentValue; - Assert.IsTrue(serverVariable.IsDirty()); - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - changedValue[0] = cachedValue; - Assert.IsTrue(serverVariable.IsDirty()); - - - serverVariable.Dispose(); - clientVariable.Dispose(); - } - - public void AssertListsMatch(ref List a, ref List b) - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists do not match: {ListStr(a)} != {ListStr(b)}"); - } - public void AssertListsDoNotMatch(ref List a, ref List b) - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists match when they should not: {ListStr(a)} == {ListStr(b)}"); - } - - - private void TestList(List testValue, List changedValue) - { - VerboseDebug($"Changing {ListStr(testValue)} to {ListStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new List(); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertListsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value = changedValue; - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertListsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Add(default); - Assert.IsTrue(serverVariable.IsDirty()); - } - - - public void AssertSetsMatch(ref HashSet a, ref HashSet b) where T : IEquatable - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Sets do not match: {HashSetStr(a)} != {HashSetStr(b)}"); - } - public void AssertSetsDoNotMatch(ref HashSet a, ref HashSet b) where T : IEquatable - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Sets match when they should not: {HashSetStr(a)} == {HashSetStr(b)}"); - } - - private void TestHashSet(HashSet testValue, HashSet changedValue) where T : IEquatable - { - VerboseDebug($"Changing {HashSetStr(testValue)} to {HashSetStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new HashSet(); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertSetsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value = changedValue; - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertSetsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Add(default); - Assert.IsTrue(serverVariable.IsDirty()); - } - - - public void AssertMapsMatch(ref Dictionary a, ref Dictionary b) - where TKey : IEquatable - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Maps do not match: {DictionaryStr(a)} != {DictionaryStr(b)}"); - } - - public void AssertMapsDoNotMatch(ref Dictionary a, ref Dictionary b) - where TKey : IEquatable - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Maps match when they should not: {DictionaryStr(a)} != {DictionaryStr(b)}"); - } - - private void TestDictionary(Dictionary testValue, Dictionary changedValue) - where TKey : IEquatable - { - VerboseDebug($"Changing {DictionaryStr(testValue)} to {DictionaryStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new Dictionary(); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertMapsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value = changedValue; - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertMapsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - foreach (var kvp in testValue) - { - if (!serverVariable.Value.ContainsKey(kvp.Key)) - { - serverVariable.Value.Add(kvp.Key, kvp.Value); - } - } - Assert.IsTrue(serverVariable.IsDirty()); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public void AssertListsMatch(ref NativeList a, ref NativeList b) where T : unmanaged - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists do not match: {NativeListStr(a)} != {NativeListStr(b)}"); - } - public void AssertListsDoNotMatch(ref NativeList a, ref NativeList b) where T : unmanaged - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Lists match when they should not: {NativeListStr(a)} == {NativeListStr(b)}"); - } - - - private void TestValueTypeNativeList(NativeList testValue, NativeList changedValue) where T : unmanaged - { - VerboseDebug($"Changing {NativeListStr(testValue)} to {NativeListStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new NativeList(1, Allocator.Temp); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertListsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value.Dispose(); - serverVariable.Value = changedValue; - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertListsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertListsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertListsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Add(default); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.Dispose(); - clientVariable.Dispose(); - } - - - public void AssertSetsMatch(ref NativeHashSet a, ref NativeHashSet b) where T : unmanaged, IEquatable - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Sets do not match: {NativeHashSetStr(a)} != {NativeHashSetStr(b)}"); - } - public void AssertSetsDoNotMatch(ref NativeHashSet a, ref NativeHashSet b) where T : unmanaged, IEquatable - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Sets match when they should not: {NativeHashSetStr(a)} == {NativeHashSetStr(b)}"); - } - - private void TestValueTypeNativeHashSet(NativeHashSet testValue, NativeHashSet changedValue) where T : unmanaged, IEquatable - { - VerboseDebug($"Changing {NativeHashSetStr(testValue)} to {NativeHashSetStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new NativeHashSet(1, Allocator.Temp); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertSetsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value.Dispose(); - serverVariable.Value = changedValue; - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertSetsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertSetsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertSetsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Add(default); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.Dispose(); - clientVariable.Dispose(); - } - - - public void AssertMapsMatch(ref NativeHashMap a, ref NativeHashMap b) - where TKey : unmanaged, IEquatable - where TVal : unmanaged - { - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Maps do not match: {NativeHashMapStr(a)} != {NativeHashMapStr(b)}"); - } - - public void AssertMapsDoNotMatch(ref NativeHashMap a, ref NativeHashMap b) - where TKey : unmanaged, IEquatable - where TVal : unmanaged - { - Assert.IsFalse(NetworkVariableSerialization>.AreEqual(ref a, ref b), - $"Maps match when they should not: {NativeHashMapStr(a)} != {NativeHashMapStr(b)}"); - } - - private void TestValueTypeNativeHashMap(NativeHashMap testValue, NativeHashMap changedValue) - where TKey : unmanaged, IEquatable - where TVal : unmanaged - { - VerboseDebug($"Changing {NativeHashMapStr(testValue)} to {NativeHashMapStr(changedValue)}"); - var serverVariable = new NetworkVariable>(testValue); - var inPlaceList = new NativeHashMap(1, Allocator.Temp); - var clientVariable = new NetworkVariable>(inPlaceList); - using var writer = new FastBufferWriter(1024, Allocator.Temp, int.MaxValue); - serverVariable.WriteField(writer); - - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadField(reader); - - AssertMapsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - serverVariable.Value.Dispose(); - serverVariable.Value = changedValue; - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - writer.Seek(0); - - serverVariable.WriteDelta(writer); - - AssertMapsDoNotMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - using var reader2 = new FastBufferReader(writer, Allocator.None); - clientVariable.ReadDelta(reader2, false); - AssertMapsMatch(ref serverVariable.RefValue(), ref clientVariable.RefValue()); - // Lists are deserialized in place so this should ALWAYS be true. Checking it every time to make sure! - AssertMapsMatch(ref clientVariable.RefValue(), ref inPlaceList); - - serverVariable.ResetDirty(); - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Clear(); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.ResetDirty(); - - Assert.IsFalse(serverVariable.IsDirty()); - serverVariable.Value.Add(default, default); - Assert.IsTrue(serverVariable.IsDirty()); - - serverVariable.Dispose(); - clientVariable.Dispose(); - } -#endif - [Test] - public void WhenSerializingAndDeserializingValueTypeNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - TestValueType(byte.MinValue + 5, byte.MaxValue); - } - else if (testType == typeof(sbyte)) - { - TestValueType(sbyte.MinValue + 5, sbyte.MaxValue); - } - else if (testType == typeof(short)) - { - TestValueType(short.MinValue + 5, short.MaxValue); - } - else if (testType == typeof(ushort)) - { - TestValueType(ushort.MinValue + 5, ushort.MaxValue); - } - else if (testType == typeof(int)) - { - TestValueType(int.MinValue + 5, int.MaxValue); - } - else if (testType == typeof(uint)) - { - TestValueType(uint.MinValue + 5, uint.MaxValue); - } - else if (testType == typeof(long)) - { - TestValueType(long.MinValue + 5, long.MaxValue); - } - else if (testType == typeof(ulong)) - { - TestValueType(ulong.MinValue + 5, ulong.MaxValue); - } - else if (testType == typeof(bool)) - { - TestValueType(true, false); - } - else if (testType == typeof(char)) - { - TestValueType('z', ' '); - } - else if (testType == typeof(float)) - { - TestValueType(float.MinValue + 5.12345678f, float.MaxValue); - } - else if (testType == typeof(double)) - { - TestValueType(double.MinValue + 5.12345678, double.MaxValue); - } - else if (testType == typeof(ByteEnum)) - { - TestValueType(ByteEnum.B, ByteEnum.C); - } - else if (testType == typeof(SByteEnum)) - { - TestValueType(SByteEnum.B, SByteEnum.C); - } - else if (testType == typeof(ShortEnum)) - { - TestValueType(ShortEnum.B, ShortEnum.C); - } - else if (testType == typeof(UShortEnum)) - { - TestValueType(UShortEnum.B, UShortEnum.C); - } - else if (testType == typeof(IntEnum)) - { - TestValueType(IntEnum.B, IntEnum.C); - } - else if (testType == typeof(UIntEnum)) - { - TestValueType(UIntEnum.B, UIntEnum.C); - } - else if (testType == typeof(LongEnum)) - { - TestValueType(LongEnum.B, LongEnum.C); - } - else if (testType == typeof(ULongEnum)) - { - TestValueType(ULongEnum.B, ULongEnum.C); - } - else if (testType == typeof(Vector2)) - { - TestValueType( - new Vector2(5, 10), - new Vector2(15, 20)); - } - else if (testType == typeof(Vector3)) - { - TestValueType( - new Vector3(5, 10, 15), - new Vector3(20, 25, 30)); - } - else if (testType == typeof(Vector2Int)) - { - TestValueType( - new Vector2Int(5, 10), - new Vector2Int(15, 20)); - } - else if (testType == typeof(Vector3Int)) - { - TestValueType( - new Vector3Int(5, 10, 15), - new Vector3Int(20, 25, 30)); - } - else if (testType == typeof(Vector4)) - { - TestValueType( - new Vector4(5, 10, 15, 20), - new Vector4(25, 30, 35, 40)); - } - else if (testType == typeof(Quaternion)) - { - TestValueType( - new Quaternion(5, 10, 15, 20), - new Quaternion(25, 30, 35, 40)); - } - else if (testType == typeof(Color)) - { - TestValueType( - new Color(1, 0, 0), - new Color(0, 1, 1)); - } - else if (testType == typeof(Color32)) - { - TestValueType( - new Color32(255, 0, 0, 128), - new Color32(0, 255, 255, 255)); - } - else if (testType == typeof(Ray)) - { - TestValueType( - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11))); - } - else if (testType == typeof(Ray2D)) - { - TestValueType( - new Ray2D(new Vector2(0, 1), new Vector2(2, 3)), - new Ray2D(new Vector2(4, 5), new Vector2(6, 7))); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - TestValueType(NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct()); - } - else if (testType == typeof(FixedString32Bytes)) - { - TestValueType(new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789")); - } - } - - [Test] - public void WhenSerializingAndDeserializingValueTypeNativeArrayNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - TestValueTypeNativeArray( - new NativeArray(new byte[] { byte.MinValue + 5, byte.MaxValue }, Allocator.Temp), - new NativeArray(new byte[] { 0, byte.MinValue + 10, byte.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(sbyte)) - { - TestValueTypeNativeArray( - new NativeArray(new sbyte[] { sbyte.MinValue + 5, sbyte.MaxValue }, Allocator.Temp), - new NativeArray(new sbyte[] { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(short)) - { - TestValueTypeNativeArray( - new NativeArray(new short[] { short.MinValue + 5, short.MaxValue }, Allocator.Temp), - new NativeArray(new short[] { 0, short.MinValue + 10, short.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(ushort)) - { - TestValueTypeNativeArray( - new NativeArray(new ushort[] { ushort.MinValue + 5, ushort.MaxValue }, Allocator.Temp), - new NativeArray(new ushort[] { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(int)) - { - TestValueTypeNativeArray( - new NativeArray(new int[] { int.MinValue + 5, int.MaxValue }, Allocator.Temp), - new NativeArray(new int[] { 0, int.MinValue + 10, int.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(uint)) - { - TestValueTypeNativeArray( - new NativeArray(new uint[] { uint.MinValue + 5, uint.MaxValue }, Allocator.Temp), - new NativeArray(new uint[] { 0, uint.MinValue + 10, uint.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(long)) - { - TestValueTypeNativeArray( - new NativeArray(new long[] { long.MinValue + 5, long.MaxValue }, Allocator.Temp), - new NativeArray(new long[] { 0, long.MinValue + 10, long.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(ulong)) - { - TestValueTypeNativeArray( - new NativeArray(new ulong[] { ulong.MinValue + 5, ulong.MaxValue }, Allocator.Temp), - new NativeArray(new ulong[] { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }, Allocator.Temp)); - } - else if (testType == typeof(bool)) - { - TestValueTypeNativeArray( - new NativeArray(new bool[] { true, false, true }, Allocator.Temp), - new NativeArray(new bool[] { false, true, false, true, false }, Allocator.Temp)); - } - else if (testType == typeof(char)) - { - TestValueTypeNativeArray( - new NativeArray(new char[] { 'z', ' ', '?' }, Allocator.Temp), - new NativeArray(new char[] { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }, Allocator.Temp)); - } - else if (testType == typeof(float)) - { - TestValueTypeNativeArray( - new NativeArray(new float[] { float.MinValue + 5.12345678f, float.MaxValue }, Allocator.Temp), - new NativeArray(new float[] { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }, Allocator.Temp)); - } - else if (testType == typeof(double)) - { - TestValueTypeNativeArray( - new NativeArray(new double[] { double.MinValue + 5.12345678, double.MaxValue }, Allocator.Temp), - new NativeArray(new double[] { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }, Allocator.Temp)); - } - else if (testType == typeof(ByteEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new ByteEnum[] { ByteEnum.C, ByteEnum.B, ByteEnum.A }, Allocator.Temp), - new NativeArray(new ByteEnum[] { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(SByteEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new SByteEnum[] { SByteEnum.C, SByteEnum.B, SByteEnum.A }, Allocator.Temp), - new NativeArray(new SByteEnum[] { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(ShortEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new ShortEnum[] { ShortEnum.C, ShortEnum.B, ShortEnum.A }, Allocator.Temp), - new NativeArray(new ShortEnum[] { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(UShortEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new UShortEnum[] { UShortEnum.C, UShortEnum.B, UShortEnum.A }, Allocator.Temp), - new NativeArray(new UShortEnum[] { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(IntEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new IntEnum[] { IntEnum.C, IntEnum.B, IntEnum.A }, Allocator.Temp), - new NativeArray(new IntEnum[] { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(UIntEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new UIntEnum[] { UIntEnum.C, UIntEnum.B, UIntEnum.A }, Allocator.Temp), - new NativeArray(new UIntEnum[] { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(LongEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new LongEnum[] { LongEnum.C, LongEnum.B, LongEnum.A }, Allocator.Temp), - new NativeArray(new LongEnum[] { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(ULongEnum)) - { - TestValueTypeNativeArray( - new NativeArray(new ULongEnum[] { ULongEnum.C, ULongEnum.B, ULongEnum.A }, Allocator.Temp), - new NativeArray(new ULongEnum[] { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }, Allocator.Temp)); - } - else if (testType == typeof(Vector2)) - { - TestValueTypeNativeArray( - new NativeArray(new Vector2[] { new Vector2(5, 10), new Vector2(15, 20) }, Allocator.Temp), - new NativeArray(new Vector2[] { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }, Allocator.Temp)); - } - else if (testType == typeof(Vector3)) - { - TestValueTypeNativeArray( - new NativeArray(new Vector3[] { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, Allocator.Temp), - new NativeArray(new Vector3[] { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }, Allocator.Temp)); - } - else if (testType == typeof(Vector2Int)) - { - TestValueTypeNativeArray( - new NativeArray(new Vector2Int[] { new Vector2Int(5, 10), new Vector2Int(15, 20) }, Allocator.Temp), - new NativeArray(new Vector2Int[] { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }, Allocator.Temp)); - } - else if (testType == typeof(Vector3Int)) - { - TestValueTypeNativeArray( - new NativeArray(new Vector3Int[] { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, Allocator.Temp), - new NativeArray(new Vector3Int[] { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }, Allocator.Temp)); - } - else if (testType == typeof(Vector4)) - { - TestValueTypeNativeArray( - new NativeArray(new Vector4[] { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, Allocator.Temp), - new NativeArray(new Vector4[] { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }, Allocator.Temp)); - } - else if (testType == typeof(Quaternion)) - { - TestValueTypeNativeArray( - new NativeArray(new Quaternion[] { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, Allocator.Temp), - new NativeArray(new Quaternion[] { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }, Allocator.Temp)); - } - else if (testType == typeof(Color)) - { - TestValueTypeNativeArray( - new NativeArray(new Color[] { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, Allocator.Temp), - new NativeArray(new Color[] { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }, Allocator.Temp)); - } - else if (testType == typeof(Color32)) - { - TestValueTypeNativeArray( - new NativeArray(new Color32[] { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, Allocator.Temp), - new NativeArray(new Color32[] { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }, Allocator.Temp)); - } - else if (testType == typeof(Ray)) - { - TestValueTypeNativeArray( - new NativeArray(new Ray[] - { - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), - }, Allocator.Temp), - new NativeArray(new Ray[] - { - new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), - new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), - new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), - }, Allocator.Temp)); - } - else if (testType == typeof(Ray2D)) - { - TestValueTypeNativeArray( - new NativeArray(new Ray2D[] - { - new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), - new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), - }, Allocator.Temp), - new NativeArray(new Ray2D[] - { - new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), - new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), - new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), - }, Allocator.Temp)); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - TestValueTypeNativeArray( - new NativeArray(new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, Allocator.Temp), - new NativeArray(new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, Allocator.Temp)); - } - else if (testType == typeof(FixedString32Bytes)) - { - TestValueTypeNativeArray( - new NativeArray(new FixedString32Bytes[] - { - new FixedString32Bytes("foobar"), - new FixedString32Bytes("12345678901234567890123456789") - }, Allocator.Temp), - new NativeArray(new FixedString32Bytes[] - { - new FixedString32Bytes("BazQux"), - new FixedString32Bytes("98765432109876543210987654321"), - new FixedString32Bytes("FixedString32Bytes") - }, Allocator.Temp)); - } - } - - public delegate T GetRandomElement(System.Random rand); - - public unsafe T RandGenBytes(System.Random rand) where T : unmanaged - { - var t = new T(); - T* tPtr = &t; - var s = new Span(tPtr, sizeof(T)); - rand.NextBytes(s); - return t; - } - - public FixedString32Bytes RandGenFixedString32(System.Random rand) - { - var s = new FixedString32Bytes(); - var len = rand.Next(s.Capacity); - s.Length = len; - for (var i = 0; i < len; ++i) - { - // Ascii visible character range - s[i] = (byte)rand.Next(32, 126); - } - - return s; - } - public string ArrayStr(NativeArray arr) where T : unmanaged - { - var str = "["; - var comma = false; - foreach (var item in arr) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item}"; - } - - str += "]"; - return str; - } - - public (NativeArray original, NativeArray original2, NativeArray changed, NativeArray changed2) GetArarys(GetRandomElement generator) where T : unmanaged - { - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Changes = rand.Next(12, 16); - var changed2Adds = rand.Next(-16, 16); - - var original = new NativeArray(originalSize, Allocator.Temp); - var changed = new NativeArray(changedSize, Allocator.Temp); - var original2 = new NativeArray(originalSize, Allocator.Temp); - var changed2 = new NativeArray(originalSize + changed2Adds, Allocator.Temp); - - - for (var i = 0; i < originalSize; ++i) - { - var item = generator(rand); - original[i] = item; - original2[i] = item; - if (i < changed2.Length) - { - changed2[i] = item; - } - } - for (var i = 0; i < changedSize; ++i) - { - var item = generator(rand); - changed[i] = item; - } - - for (var i = 0; i < changed2Changes; ++i) - { - var idx = rand.Next(changed2.Length - 1); - var item = generator(rand); - changed2[idx] = item; - } - - for (var i = 0; i < changed2Adds; ++i) - { - var item = generator(rand); - changed2[originalSize + i] = item; - } - - VerboseDebug($"Original: {ArrayStr(original)}"); - VerboseDebug($"Changed: {ArrayStr(changed)}"); - VerboseDebug($"Original2: {ArrayStr(original2)}"); - VerboseDebug($"Changed2: {ArrayStr(changed2)}"); - return (original, original2, changed, changed2); - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeArrayNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), - typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(sbyte)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(short)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(ushort)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(int)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(uint)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(long)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(bool)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(char)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(float)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(double)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Vector3)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Vector2Int)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Vector2Int(rand.Next(), rand.Next()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Vector3Int)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Vector4)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Quaternion)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Color)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Color32)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Color32((byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next()) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Ray)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Ray( - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(Ray2D)) - { - (var original, var original2, var changed, var changed2) = GetArarys( - (rand) => new Ray2D( - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - else if (testType == typeof(FixedString32Bytes)) - { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenFixedString32); - TestValueTypeNativeArray(original, changed); - TestValueTypeNativeArray(original2, changed2); - } - } - - - public string ListStr(List list) - { - var str = "["; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item}"; - } - - str += "]"; - return str; - } - - public string HashSetStr(HashSet list) where T : IEquatable - { - var str = "{"; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item}"; - } - - str += "}"; - return str; - } - - public string DictionaryStr(Dictionary list) - where TKey : IEquatable - { - var str = "{"; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item.Key}: {item.Value}"; - } - - str += "}"; - return str; - } - - public (List original, List original2, List changed, List changed2) GetLists(GetRandomElement generator) - { - var original = new List(); - var changed = new List(); - var original2 = new List(); - var changed2 = new List(); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Changes = rand.Next(12, 16); - var changed2Adds = rand.Next(-16, 16); - for (var i = 0; i < originalSize; ++i) - { - var item = generator(rand); - original.Add(item); - original2.Add(item); - changed2.Add(item); - } - for (var i = 0; i < changedSize; ++i) - { - var item = generator(rand); - changed.Add(item); - } - - for (var i = 0; i < changed2Changes; ++i) - { - var idx = rand.Next(changed2.Count - 1); - var item = generator(rand); - changed2[idx] = item; - } - - if (changed2Adds < 0) - { - changed2.RemoveRange(changed2.Count + changed2Adds, -changed2Adds); - } - else - { - for (var i = 0; i < changed2Adds; ++i) - { - var item = generator(rand); - changed2.Add(item); - } - - } - - VerboseDebug($"Original: {ListStr(original)}"); - VerboseDebug($"Changed: {ListStr(changed)}"); - VerboseDebug($"Original2: {ListStr(original2)}"); - VerboseDebug($"Changed2: {ListStr(changed2)}"); - return (original, original2, changed, changed2); - } - - public (HashSet original, HashSet original2, HashSet changed, HashSet changed2) GetHashSets(GetRandomElement generator) where T : IEquatable - { - var original = new HashSet(); - var changed = new HashSet(); - var original2 = new HashSet(); - var changed2 = new HashSet(); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Removes = rand.Next(12, 16); - var changed2Adds = rand.Next(12, 16); - for (var i = 0; i < originalSize; ++i) - { - var item = generator(rand); - while (original.Contains(item)) - { - item = generator(rand); - } - original.Add(item); - original2.Add(item); - changed2.Add(item); - } - for (var i = 0; i < changedSize; ++i) - { - var item = generator(rand); - while (changed.Contains(item)) - { - item = generator(rand); - } - changed.Add(item); - } - - for (var i = 0; i < changed2Removes; ++i) - { - var which = rand.Next(changed2.Count()); - T toRemove = default; - foreach (var check in changed2) - { - if (which == 0) - { - toRemove = check; - break; - } - --which; - } - - changed2.Remove(toRemove); - } - - for (var i = 0; i < changed2Adds; ++i) - { - var item = generator(rand); - while (changed2.Contains(item)) - { - item = generator(rand); - } - changed2.Add(item); - } - - VerboseDebug($"Original: {HashSetStr(original)}"); - VerboseDebug($"Changed: {HashSetStr(changed)}"); - VerboseDebug($"Original2: {HashSetStr(original2)}"); - VerboseDebug($"Changed2: {HashSetStr(changed2)}"); - return (original, original2, changed, changed2); - } - - - public (Dictionary original, Dictionary original2, Dictionary changed, Dictionary changed2) GetDictionaries(GetRandomElement keyGenerator, GetRandomElement valGenerator) - where TKey : IEquatable - { - var original = new Dictionary(); - var changed = new Dictionary(); - var original2 = new Dictionary(); - var changed2 = new Dictionary(); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Removes = rand.Next(12, 16); - var changed2Adds = rand.Next(12, 16); - var changed2Changes = rand.Next(12, 16); - for (var i = 0; i < originalSize; ++i) - { - var key = keyGenerator(rand); - while (original.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - original.Add(key, val); - original2.Add(key, val); - changed2.Add(key, val); - } - for (var i = 0; i < changedSize; ++i) - { - var key = keyGenerator(rand); - while (changed.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - changed.Add(key, val); - } - - for (var i = 0; i < changed2Removes; ++i) - { - var which = rand.Next(changed2.Count()); - TKey toRemove = default; - foreach (var check in changed2) - { - if (which == 0) - { - toRemove = check.Key; - break; - } - --which; - } - - changed2.Remove(toRemove); - } - - for (var i = 0; i < changed2Changes; ++i) - { - var which = rand.Next(changed2.Count()); - TKey key = default; - foreach (var check in changed2) - { - if (which == 0) - { - key = check.Key; - break; - } - --which; - } - - var val = valGenerator(rand); - changed2[key] = val; - } - - for (var i = 0; i < changed2Adds; ++i) - { - var key = keyGenerator(rand); - while (changed2.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - changed2.Add(key, val); - } - - VerboseDebug($"Original: {DictionaryStr(original)}"); - VerboseDebug($"Changed: {DictionaryStr(changed)}"); - VerboseDebug($"Original2: {DictionaryStr(original2)}"); - VerboseDebug($"Changed2: {DictionaryStr(changed2)}"); - return (original, original2, changed, changed2); - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeListNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), - typeof(NetworkVariableTestClass), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(sbyte)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(short)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(ushort)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(int)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(uint)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(long)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(bool)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(char)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(float)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(double)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Vector3)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Vector2Int)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Vector2Int(rand.Next(), rand.Next()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Vector3Int)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Vector4)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Quaternion)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Color)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Color32)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Color32((byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next()) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Ray)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Ray( - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(Ray2D)) - { - (var original, var original2, var changed, var changed2) = GetLists( - (rand) => new Ray2D( - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(NetworkVariableTestClass)) - { - (var original, var original2, var changed, var changed2) = GetLists((rand) => - { - return new NetworkVariableTestClass { Data = RandGenBytes(rand) }; - }); - TestList(original, changed); - TestList(original2, changed2); - } - else if (testType == typeof(FixedString32Bytes)) - { - (var original, var original2, var changed, var changed2) = GetLists(RandGenFixedString32); - TestList(original, changed); - TestList(original2, changed2); - } - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeHashSetNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(HashableNetworkVariableTestClass), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(sbyte)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(short)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(ushort)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(int)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(uint)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(long)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(bool)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(char)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(float)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(double)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Vector3)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Vector2Int)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Vector2Int(rand.Next(), rand.Next()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Vector3Int)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Vector4)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Quaternion)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(Color)) - { - (var original, var original2, var changed, var changed2) = GetHashSets( - (rand) => new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(HashableNetworkVariableTestClass)) - { - (var original, var original2, var changed, var changed2) = GetHashSets((rand) => - { - return new HashableNetworkVariableTestClass { Data = RandGenBytes(rand) }; - }); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - else if (testType == typeof(FixedString32Bytes)) - { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenFixedString32); - TestHashSet(original, changed); - TestHashSet(original2, changed2); - } - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeDictionaryNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(ulong), typeof(Vector2), typeof(HashMapKeyClass))] Type keyType, - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(HashMapValClass), typeof(FixedString32Bytes))] - Type valType) - { - if (valType == typeof(byte)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(sbyte)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(short)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(ushort)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(uint)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(long)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(ulong)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(bool)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(char)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(float)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(double)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Vector2)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Vector3)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Vector2Int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Vector3Int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Vector4)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(Quaternion)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(HashMapValClass)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new HashMapValClass { Data = RandGenBytes(rand) }); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, (rand) => new HashMapValClass { Data = RandGenBytes(rand) }); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new HashMapValClass { Data = RandGenBytes(rand) }); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, (rand) => new HashMapValClass { Data = RandGenBytes(rand) }); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - else if (valType == typeof(FixedString32Bytes)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenFixedString32); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenFixedString32); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenFixedString32); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyClass)) - { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenFixedString32); - TestDictionary(original, changed); - TestDictionary(original2, changed2); - } - } - } - - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [Test] - public void WhenSerializingAndDeserializingValueTypeNativeListNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { byte.MinValue + 5, byte.MaxValue }, - new NativeList(Allocator.Temp) { 0, byte.MinValue + 10, byte.MaxValue - 10 }); - } - else if (testType == typeof(sbyte)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { sbyte.MinValue + 5, sbyte.MaxValue }, - new NativeList(Allocator.Temp) { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }); - } - else if (testType == typeof(short)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { short.MinValue + 5, short.MaxValue }, - new NativeList(Allocator.Temp) { 0, short.MinValue + 10, short.MaxValue - 10 }); - } - else if (testType == typeof(ushort)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { ushort.MinValue + 5, ushort.MaxValue }, - new NativeList(Allocator.Temp) { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }); - } - else if (testType == typeof(int)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { int.MinValue + 5, int.MaxValue }, - new NativeList(Allocator.Temp) { 0, int.MinValue + 10, int.MaxValue - 10 }); - } - else if (testType == typeof(uint)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { uint.MinValue + 5, uint.MaxValue }, - new NativeList(Allocator.Temp) { 0, uint.MinValue + 10, uint.MaxValue - 10 }); - } - else if (testType == typeof(long)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { long.MinValue + 5, long.MaxValue }, - new NativeList(Allocator.Temp) { 0, long.MinValue + 10, long.MaxValue - 10 }); - } - else if (testType == typeof(ulong)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { ulong.MinValue + 5, ulong.MaxValue }, - new NativeList(Allocator.Temp) { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }); - } - else if (testType == typeof(bool)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { true, false, true }, - new NativeList(Allocator.Temp) { false, true, false, true, false }); - } - else if (testType == typeof(char)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { 'z', ' ', '?' }, - new NativeList(Allocator.Temp) { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }); - } - else if (testType == typeof(float)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { float.MinValue + 5.12345678f, float.MaxValue }, - new NativeList(Allocator.Temp) { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }); - } - else if (testType == typeof(double)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { double.MinValue + 5.12345678, double.MaxValue }, - new NativeList(Allocator.Temp) { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }); - } - else if (testType == typeof(ByteEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { ByteEnum.C, ByteEnum.B, ByteEnum.A }, - new NativeList(Allocator.Temp) { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }); - } - else if (testType == typeof(SByteEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { SByteEnum.C, SByteEnum.B, SByteEnum.A }, - new NativeList(Allocator.Temp) { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }); - } - else if (testType == typeof(ShortEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { ShortEnum.C, ShortEnum.B, ShortEnum.A }, - new NativeList(Allocator.Temp) { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }); - } - else if (testType == typeof(UShortEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { UShortEnum.C, UShortEnum.B, UShortEnum.A }, - new NativeList(Allocator.Temp) { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }); - } - else if (testType == typeof(IntEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { IntEnum.C, IntEnum.B, IntEnum.A }, - new NativeList(Allocator.Temp) { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }); - } - else if (testType == typeof(UIntEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { UIntEnum.C, UIntEnum.B, UIntEnum.A }, - new NativeList(Allocator.Temp) { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }); - } - else if (testType == typeof(LongEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { LongEnum.C, LongEnum.B, LongEnum.A }, - new NativeList(Allocator.Temp) { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }); - } - else if (testType == typeof(ULongEnum)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { ULongEnum.C, ULongEnum.B, ULongEnum.A }, - new NativeList(Allocator.Temp) { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }); - } - else if (testType == typeof(Vector2)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Vector2(5, 10), new Vector2(15, 20) }, - new NativeList(Allocator.Temp) { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }); - } - else if (testType == typeof(Vector3)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, - new NativeList(Allocator.Temp) { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }); - } - else if (testType == typeof(Vector2Int)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Vector2Int(5, 10), new Vector2Int(15, 20) }, - new NativeList(Allocator.Temp) { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }); - } - else if (testType == typeof(Vector3Int)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, - new NativeList(Allocator.Temp) { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }); - } - else if (testType == typeof(Vector4)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, - new NativeList(Allocator.Temp) { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }); - } - else if (testType == typeof(Quaternion)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, - new NativeList(Allocator.Temp) { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }); - } - else if (testType == typeof(Color)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, - new NativeList(Allocator.Temp) { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }); - } - else if (testType == typeof(Color32)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, - new NativeList(Allocator.Temp) { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }); - } - else if (testType == typeof(Ray)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) - { - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), - }, - new NativeList(Allocator.Temp) - { - new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), - new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), - new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), - }); - } - else if (testType == typeof(Ray2D)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) - { - new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), - new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), - }, - new NativeList(Allocator.Temp) - { - new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), - new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), - new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), - }); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, - new NativeList(Allocator.Temp) - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }); - } - else if (testType == typeof(FixedString32Bytes)) - { - TestValueTypeNativeList( - new NativeList(Allocator.Temp) - { - new FixedString32Bytes("foobar"), - new FixedString32Bytes("12345678901234567890123456789") - }, - new NativeList(Allocator.Temp) - { - new FixedString32Bytes("BazQux"), - new FixedString32Bytes("98765432109876543210987654321"), - new FixedString32Bytes("FixedString32Bytes") - }); - } - } - - public string NativeListStr(NativeList list) where T : unmanaged - { - var str = "["; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item}"; - } - - str += "]"; - return str; - } - - public string NativeHashSetStr(NativeHashSet list) where T : unmanaged, IEquatable - { - var str = "{"; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item}"; - } - - str += "}"; - return str; - } - - public string NativeHashMapStr(NativeHashMap list) - where TKey : unmanaged, IEquatable - where TVal : unmanaged - { - var str = "{"; - var comma = false; - foreach (var item in list) - { - if (comma) - { - str += ", "; - } - - comma = true; - str += $"{item.Key}: {item.Value}"; - } - - str += "}"; - return str; - } - - public (NativeList original, NativeList original2, NativeList changed, NativeList changed2) GetNativeLists(GetRandomElement generator) where T : unmanaged - { - var original = new NativeList(Allocator.Temp); - var changed = new NativeList(Allocator.Temp); - var original2 = new NativeList(Allocator.Temp); - var changed2 = new NativeList(Allocator.Temp); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Changes = rand.Next(12, 16); - var changed2Adds = rand.Next(-16, 16); - for (var i = 0; i < originalSize; ++i) - { - var item = generator(rand); - original.Add(item); - original2.Add(item); - changed2.Add(item); - } - for (var i = 0; i < changedSize; ++i) - { - var item = generator(rand); - changed.Add(item); - } - - for (var i = 0; i < changed2Changes; ++i) - { - var idx = rand.Next(changed2.Length - 1); - var item = generator(rand); - changed2[idx] = item; - } - - if (changed2Adds < 0) - { - changed2.Resize(changed2.Length + changed2Adds, NativeArrayOptions.UninitializedMemory); - } - else - { - for (var i = 0; i < changed2Adds; ++i) - { - var item = generator(rand); - changed2.Add(item); - } - - } - - VerboseDebug($"Original: {NativeListStr(original)}"); - VerboseDebug($"Changed: {NativeListStr(changed)}"); - VerboseDebug($"Original2: {NativeListStr(original2)}"); - VerboseDebug($"Changed2: {NativeListStr(changed2)}"); - return (original, original2, changed, changed2); - } - - public (NativeHashSet original, NativeHashSet original2, NativeHashSet changed, NativeHashSet changed2) GetNativeHashSets(GetRandomElement generator) where T : unmanaged, IEquatable - { - var original = new NativeHashSet(16, Allocator.Temp); - var changed = new NativeHashSet(16, Allocator.Temp); - var original2 = new NativeHashSet(16, Allocator.Temp); - var changed2 = new NativeHashSet(16, Allocator.Temp); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Removes = rand.Next(12, 16); - var changed2Adds = rand.Next(12, 16); - for (var i = 0; i < originalSize; ++i) - { - var item = generator(rand); - while (original.Contains(item)) - { - item = generator(rand); - } - original.Add(item); - original2.Add(item); - changed2.Add(item); - } - for (var i = 0; i < changedSize; ++i) - { - var item = generator(rand); - while (changed.Contains(item)) - { - item = generator(rand); - } - changed.Add(item); - } - - for (var i = 0; i < changed2Removes; ++i) - { -#if UTP_TRANSPORT_2_0_ABOVE - var which = rand.Next(changed2.Count); -#else - var which = rand.Next(changed2.Count()); -#endif - T toRemove = default; - foreach (var check in changed2) - { - if (which == 0) - { - toRemove = check; - break; - } - --which; - } - - changed2.Remove(toRemove); - } - - for (var i = 0; i < changed2Adds; ++i) - { - var item = generator(rand); - while (changed2.Contains(item)) - { - item = generator(rand); - } - changed2.Add(item); - } - - VerboseDebug($"Original: {NativeHashSetStr(original)}"); - VerboseDebug($"Changed: {NativeHashSetStr(changed)}"); - VerboseDebug($"Original2: {NativeHashSetStr(original2)}"); - VerboseDebug($"Changed2: {NativeHashSetStr(changed2)}"); - return (original, original2, changed, changed2); - } - - - public (NativeHashMap original, NativeHashMap original2, NativeHashMap changed, NativeHashMap changed2) GetMaps(GetRandomElement keyGenerator, GetRandomElement valGenerator) - where TKey : unmanaged, IEquatable - where TVal : unmanaged - { - var original = new NativeHashMap(16, Allocator.Temp); - var changed = new NativeHashMap(16, Allocator.Temp); - var original2 = new NativeHashMap(16, Allocator.Temp); - var changed2 = new NativeHashMap(16, Allocator.Temp); - - var rand = new System.Random(); - var originalSize = rand.Next(32, 64); - var changedSize = rand.Next(32, 64); - var changed2Removes = rand.Next(12, 16); - var changed2Adds = rand.Next(12, 16); - var changed2Changes = rand.Next(12, 16); - for (var i = 0; i < originalSize; ++i) - { - var key = keyGenerator(rand); - while (original.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - original.Add(key, val); - original2.Add(key, val); - changed2.Add(key, val); - } - for (var i = 0; i < changedSize; ++i) - { - var key = keyGenerator(rand); - while (changed.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - changed.Add(key, val); - } - - for (var i = 0; i < changed2Removes; ++i) - { -#if UTP_TRANSPORT_2_0_ABOVE - var which = rand.Next(changed2.Count); -#else - var which = rand.Next(changed2.Count()); -#endif - TKey toRemove = default; - foreach (var check in changed2) - { - if (which == 0) - { - toRemove = check.Key; - break; - } - --which; - } - - changed2.Remove(toRemove); - } - - for (var i = 0; i < changed2Changes; ++i) - { -#if UTP_TRANSPORT_2_0_ABOVE - var which = rand.Next(changed2.Count); -#else - var which = rand.Next(changed2.Count()); -#endif - TKey key = default; - foreach (var check in changed2) - { - if (which == 0) - { - key = check.Key; - break; - } - --which; - } - - var val = valGenerator(rand); - changed2[key] = val; - } - - for (var i = 0; i < changed2Adds; ++i) - { - var key = keyGenerator(rand); - while (changed2.ContainsKey(key)) - { - key = keyGenerator(rand); - } - var val = valGenerator(rand); - changed2.Add(key, val); - } - - VerboseDebug($"Original: {NativeHashMapStr(original)}"); - VerboseDebug($"Changed: {NativeHashMapStr(changed)}"); - VerboseDebug($"Original2: {NativeHashMapStr(original2)}"); - VerboseDebug($"Changed2: {NativeHashMapStr(changed2)}"); - return (original, original2, changed, changed2); - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeListNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(Color), typeof(Color32), typeof(Ray), typeof(Ray2D), - typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(sbyte)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(short)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(ushort)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(int)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(uint)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(long)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(bool)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(char)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(float)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(double)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Vector3)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Vector2Int)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Vector2Int(rand.Next(), rand.Next()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Vector3Int)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Vector4)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Quaternion)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Color)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Color32)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Color32((byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next(), (byte)rand.Next()) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Ray)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Ray( - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(Ray2D)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists( - (rand) => new Ray2D( - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), - new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ) - ); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - else if (testType == typeof(FixedString32Bytes)) - { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenFixedString32); - TestValueTypeNativeList(original, changed); - TestValueTypeNativeList(original2, changed2); - } - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashSetNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(HashableNetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(sbyte)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(short)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(ushort)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(int)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(uint)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(long)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(bool)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(char)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(float)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(double)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Vector3)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Vector2Int)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Vector2Int(rand.Next(), rand.Next()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Vector3Int)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Vector4)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Quaternion)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(Color)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets( - (rand) => new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()) - ); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(HashableNetworkVariableTestStruct)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - else if (testType == typeof(FixedString32Bytes)) - { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenFixedString32); - TestValueTypeNativeHashSet(original, changed); - TestValueTypeNativeHashSet(original2, changed2); - } - } - - [Test] - [Repeat(5)] - public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashMapNetworkVariables_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(ulong), typeof(Vector2), typeof(HashMapKeyStruct))] Type keyType, - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), - typeof(Quaternion), typeof(HashMapValStruct), typeof(FixedString32Bytes))] - Type valType) - { - if (valType == typeof(byte)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(sbyte)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(short)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(ushort)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(uint)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(long)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(ulong)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(bool)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(char)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(float)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(double)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Vector2)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Vector3)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Vector2Int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector2Int(rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Vector3Int)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector3Int(rand.Next(), rand.Next(), rand.Next())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Vector4)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Vector4((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(Quaternion)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, (rand) => new Quaternion((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble())); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(HashMapValStruct)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - else if (valType == typeof(FixedString32Bytes)) - { - if (keyType == typeof(byte)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenFixedString32); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(ulong)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenFixedString32); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - else if (keyType == typeof(Vector2)) - { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenFixedString32); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - - } - else if (keyType == typeof(HashMapKeyStruct)) - { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenFixedString32); - TestValueTypeNativeHashMap(original, changed); - TestValueTypeNativeHashMap(original2, changed2); - } - } - } - -#endif - - [Test] - public void TestManagedINetworkSerializableNetworkVariablesDeserializeInPlace() - { - var variable = new NetworkVariable - { - Value = new ManagedNetworkSerializableType - { - InMemoryValue = 1, - Ints = new[] { 2, 3, 4 }, - Str = "five", - Embedded = new EmbeddedManagedNetworkSerializableType { Int = 6 } - } - }; - - using var writer = new FastBufferWriter(1024, Allocator.Temp); - variable.WriteField(writer); - Assert.AreEqual(1, variable.Value.InMemoryValue); - Assert.AreEqual(new[] { 2, 3, 4 }, variable.Value.Ints); - Assert.AreEqual("five", variable.Value.Str); - Assert.AreEqual(6, variable.Value.Embedded.Int); - variable.Value = new ManagedNetworkSerializableType - { - InMemoryValue = 10, - Ints = new[] { 20, 30, 40, 50 }, - Str = "sixty", - Embedded = new EmbeddedManagedNetworkSerializableType { Int = 60 } - }; - - using var reader = new FastBufferReader(writer, Allocator.None); - variable.ReadField(reader); - Assert.AreEqual(10, variable.Value.InMemoryValue, "In-memory value was not the same - in-place deserialization should not change this"); - Assert.AreEqual(new[] { 2, 3, 4 }, variable.Value.Ints, "Ints were not correctly deserialized"); - Assert.AreEqual("five", variable.Value.Str, "Str was not correctly deserialized"); - Assert.AreEqual(6, variable.Value.Embedded.Int, "Embedded int was not correctly deserialized"); - } - - [Test] - public void TestUnmnagedINetworkSerializableNetworkVariablesDeserializeInPlace() - { - var variable = new NetworkVariable - { - Value = new UnmanagedNetworkSerializableType - { - InMemoryValue = 1, - Int = 2, - Str = "three" - } - }; - using var writer = new FastBufferWriter(1024, Allocator.Temp); - variable.WriteField(writer); - Assert.AreEqual(1, variable.Value.InMemoryValue); - Assert.AreEqual(2, variable.Value.Int); - Assert.AreEqual("three", variable.Value.Str); - variable.Value = new UnmanagedNetworkSerializableType - { - InMemoryValue = 10, - Int = 20, - Str = "thirty" - }; - - using var reader = new FastBufferReader(writer, Allocator.None); - variable.ReadField(reader); - Assert.AreEqual(10, variable.Value.InMemoryValue, "In-memory value was not the same - in-place deserialization should not change this"); - Assert.AreEqual(2, variable.Value.Int, "Int was not correctly deserialized"); - Assert.AreEqual("three", variable.Value.Str, "Str was not correctly deserialized"); - } - - private float m_OriginalTimeScale = 1.0f; - - protected override IEnumerator OnSetup() - { - m_OriginalTimeScale = Time.timeScale; - yield return null; - } - - protected override IEnumerator OnTearDown() - { - Time.timeScale = m_OriginalTimeScale; - - m_NetworkListPredicateHandler = null; - yield return base.OnTearDown(); - } - } -} -#endif diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs.meta deleted file mode 100644 index 5073e66..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d271d8738dbbb5e4aa0cae91b663f183 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs b/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs deleted file mode 100644 index f50811b..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs +++ /dev/null @@ -1,937 +0,0 @@ -using System; -using System.Collections.Generic; -using Unity.Collections; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetVarPermTestComp : NetworkBehaviour - { - public NetworkVariable OwnerWritable_Position = new NetworkVariable(Vector3.one, NetworkVariableBase.DefaultReadPerm, NetworkVariableWritePermission.Owner); - public NetworkVariable ServerWritable_Position = new NetworkVariable(Vector3.one, NetworkVariableBase.DefaultReadPerm, NetworkVariableWritePermission.Server); - public NetworkVariable OwnerReadWrite_Position = new NetworkVariable(Vector3.one, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner); - } - - internal class NetworkVariableMiddleclass : NetworkVariable - { - - } - - internal class NetworkVariableSubclass : NetworkVariableMiddleclass - { - - } - - internal class NetworkBehaviourWithNetVarArray : NetworkBehaviour - { - public NetworkVariable Int0 = new NetworkVariable(); - public NetworkVariable Int1 = new NetworkVariable(); - public NetworkVariable Int2 = new NetworkVariable(); - public NetworkVariable Int3 = new NetworkVariable(); - public NetworkVariable Int4 = new NetworkVariable(); - public NetworkVariable[] AllInts = new NetworkVariable[5]; - - public int InitializedFieldCount => NetworkVariableFields.Count; - - - private void Awake() - { - AllInts[0] = Int0; - AllInts[1] = Int1; - AllInts[2] = Int2; - AllInts[3] = Int3; - AllInts[4] = Int4; - } - } - - internal struct TypeReferencedOnlyInCustomSerialization1 : INetworkSerializeByMemcpy - { - public int I; - } - - internal struct TypeReferencedOnlyInCustomSerialization2 : INetworkSerializeByMemcpy - { - public int I; - } - - internal struct TypeReferencedOnlyInCustomSerialization3 : INetworkSerializeByMemcpy - { - public int I; - } - - internal struct TypeReferencedOnlyInCustomSerialization4 : INetworkSerializeByMemcpy - { - public int I; - } - - internal struct TypeReferencedOnlyInCustomSerialization5 : INetworkSerializeByMemcpy - { - public int I; - } - - internal struct TypeReferencedOnlyInCustomSerialization6 : INetworkSerializeByMemcpy - { - public int I; - } - - // Both T and U are serializable - [GenerateSerializationForGenericParameter(0)] - [GenerateSerializationForGenericParameter(1)] - internal class CustomSerializableClass - { - - } - - // Only U is serializable - [GenerateSerializationForGenericParameter(1)] - internal class CustomSerializableBaseClass - { - - } - - // T is serializable, passes TypeReferencedOnlyInCustomSerialization3 as U to the subclass, making it serializable - [GenerateSerializationForGenericParameter(0)] - internal class CustomSerializableSubclass : CustomSerializableBaseClass - { - - } - - // T is serializable, passes TypeReferencedOnlyInCustomSerialization3 as U to the subclass, making it serializable - [GenerateSerializationForGenericParameter(0)] - internal class CustomSerializableSubclassWithNativeArray : CustomSerializableBaseClass> - { - - } - - internal class CustomGenericSerializationTestBehaviour : NetworkBehaviour - { - public CustomSerializableClass Value1; - public CustomSerializableClass, NativeArray> Value2; - public CustomSerializableSubclass Value3; - public CustomSerializableSubclassWithNativeArray> Value4; - } - - [GenerateSerializationForType(typeof(TypeReferencedOnlyInCustomSerialization5))] - [GenerateSerializationForType(typeof(NativeArray))] - internal struct SomeRandomStruct - { - [GenerateSerializationForType(typeof(TypeReferencedOnlyInCustomSerialization6))] - [GenerateSerializationForType(typeof(NativeArray))] - public void Foo() - { - - } - } - - internal struct TemplatedValueOnlyReferencedByNetworkVariableSubclass : INetworkSerializeByMemcpy - where T : unmanaged - { - public T Value; - } - - public enum ByteEnum : byte - { - A, - B, - C = byte.MaxValue - } - public enum SByteEnum : sbyte - { - A, - B, - C = sbyte.MaxValue - } - public enum ShortEnum : short - { - A, - B, - C = short.MaxValue - } - public enum UShortEnum : ushort - { - A, - B, - C = ushort.MaxValue - } - public enum IntEnum : int - { - A, - B, - C = int.MaxValue - } - public enum UIntEnum : uint - { - A, - B, - C = uint.MaxValue - } - public enum LongEnum : long - { - A, - B, - C = long.MaxValue - } - public enum ULongEnum : ulong - { - A, - B, - C = ulong.MaxValue - } - - internal struct HashableNetworkVariableTestStruct : INetworkSerializeByMemcpy, IEquatable - { - public byte A; - public short B; - public ushort C; - public int D; - public uint E; - public long F; - public ulong G; - public bool H; - public char I; - public float J; - public double K; - - public bool Equals(HashableNetworkVariableTestStruct other) - { - return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K); - } - - public override bool Equals(object obj) - { - return obj is HashableNetworkVariableTestStruct other && Equals(other); - } - - public override int GetHashCode() - { - var hashCode = new HashCode(); - hashCode.Add(A); - hashCode.Add(B); - hashCode.Add(C); - hashCode.Add(D); - hashCode.Add(E); - hashCode.Add(F); - hashCode.Add(G); - hashCode.Add(H); - hashCode.Add(I); - hashCode.Add(J); - hashCode.Add(K); - return hashCode.ToHashCode(); - } - } - - internal struct HashMapKeyStruct : INetworkSerializeByMemcpy, IEquatable - { - public byte A; - public short B; - public ushort C; - public int D; - public uint E; - public long F; - public ulong G; - public bool H; - public char I; - public float J; - public double K; - - public bool Equals(HashMapKeyStruct other) - { - return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K); - } - - public override bool Equals(object obj) - { - return obj is HashMapKeyStruct other && Equals(other); - } - - public override int GetHashCode() - { - var hashCode = new HashCode(); - hashCode.Add(A); - hashCode.Add(B); - hashCode.Add(C); - hashCode.Add(D); - hashCode.Add(E); - hashCode.Add(F); - hashCode.Add(G); - hashCode.Add(H); - hashCode.Add(I); - hashCode.Add(J); - hashCode.Add(K); - return hashCode.ToHashCode(); - } - } - - internal struct HashMapValStruct : INetworkSerializeByMemcpy, IEquatable - { - public byte A; - public short B; - public ushort C; - public int D; - public uint E; - public long F; - public ulong G; - public bool H; - public char I; - public float J; - public double K; - - public bool Equals(HashMapValStruct other) - { - return A == other.A && B == other.B && C == other.C && D == other.D && E == other.E && F == other.F && G == other.G && H == other.H && I == other.I && J.Equals(other.J) && K.Equals(other.K); - } - - public override bool Equals(object obj) - { - return obj is HashMapValStruct other && Equals(other); - } - - public override int GetHashCode() - { - var hashCode = new HashCode(); - hashCode.Add(A); - hashCode.Add(B); - hashCode.Add(C); - hashCode.Add(D); - hashCode.Add(E); - hashCode.Add(F); - hashCode.Add(G); - hashCode.Add(H); - hashCode.Add(I); - hashCode.Add(J); - hashCode.Add(K); - return hashCode.ToHashCode(); - } - } - - internal struct NetworkVariableTestStruct : INetworkSerializeByMemcpy - { - public byte A; - public short B; - public ushort C; - public int D; - public uint E; - public long F; - public ulong G; - public bool H; - public char I; - public float J; - public double K; - - private static System.Random s_Random = new System.Random(); - - public static NetworkVariableTestStruct GetTestStruct() - { - var testStruct = new NetworkVariableTestStruct - { - A = (byte)s_Random.Next(), - B = (short)s_Random.Next(), - C = (ushort)s_Random.Next(), - D = s_Random.Next(), - E = (uint)s_Random.Next(), - F = ((long)s_Random.Next() << 32) + s_Random.Next(), - G = ((ulong)s_Random.Next() << 32) + (ulong)s_Random.Next(), - H = true, - I = '\u263a', - J = (float)s_Random.NextDouble(), - K = s_Random.NextDouble(), - }; - - return testStruct; - } - } - - - internal class HashableNetworkVariableTestClass : INetworkSerializable, IEquatable - { - public HashableNetworkVariableTestStruct Data; - - public bool Equals(HashableNetworkVariableTestClass other) - { - return Data.Equals(other.Data); - } - - public override bool Equals(object obj) - { - return obj is HashableNetworkVariableTestClass other && Equals(other); - } - - public override int GetHashCode() - { - return Data.GetHashCode(); - } - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Data); - } - } - - internal class HashMapKeyClass : INetworkSerializable, IEquatable - { - public HashMapKeyStruct Data; - - public bool Equals(HashMapKeyClass other) - { - return Data.Equals(other.Data); - } - - public override bool Equals(object obj) - { - return obj is HashMapKeyClass other && Equals(other); - } - - public override int GetHashCode() - { - return Data.GetHashCode(); - } - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Data); - } - } - - internal class HashMapValClass : INetworkSerializable, IEquatable - { - public HashMapValStruct Data; - - public bool Equals(HashMapValClass other) - { - return Data.Equals(other.Data); - } - - public override bool Equals(object obj) - { - return obj is HashMapValClass other && Equals(other); - } - - public override int GetHashCode() - { - return Data.GetHashCode(); - } - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Data); - } - } - - internal class NetworkVariableTestClass : INetworkSerializable, IEquatable - { - public NetworkVariableTestStruct Data; - - public bool Equals(NetworkVariableTestClass other) - { - return NetworkVariableSerialization.AreEqual(ref Data, ref other.Data); - } - - public override bool Equals(object obj) - { - return obj is NetworkVariableTestClass other && Equals(other); - } - - // This type is not used for hashing, we just need to implement IEquatable to verify lists match. - public override int GetHashCode() - { - return 0; - } - - public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter - { - serializer.SerializeValue(ref Data); - } - } - - - // The ILPP code for NetworkVariables to determine how to serialize them relies on them existing as fields of a NetworkBehaviour to find them. - // Some of the tests below create NetworkVariables on the stack, so this class is here just to make sure the relevant types are all accounted for. - internal class NetVarILPPClassForTests : NetworkBehaviour - { - public NetworkVariable ByteVar; - public NetworkVariable> ByteArrayVar; - public NetworkVariable> ByteManagedListVar; - public NetworkVariable> ByteManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ByteListVar; - public NetworkVariable> ByteHashSetVar; - public NetworkVariable> ByteByteHashMapVar; - public NetworkVariable> ULongByteHashMapVar; - public NetworkVariable> Vector2ByteHashMapVar; - public NetworkVariable> HashMapKeyStructByteHashMapVar; -#endif - public NetworkVariable> ByteByteDictionaryVar; - public NetworkVariable> ULongByteDictionaryVar; - public NetworkVariable> Vector2ByteDictionaryVar; - public NetworkVariable> HashMapKeyClassByteDictionaryVar; - - public NetworkVariable SbyteVar; - public NetworkVariable> SbyteArrayVar; - public NetworkVariable> SbyteManagedListVar; - public NetworkVariable> SbyteManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> SbyteListVar; - public NetworkVariable> SbyteHashSetVar; - public NetworkVariable> ByteSbyteHashMapVar; - public NetworkVariable> ULongSbyteHashMapVar; - public NetworkVariable> Vector2SbyteHashMapVar; - public NetworkVariable> HashMapKeyStructSbyteHashMapVar; -#endif - public NetworkVariable> ByteSbyteDictionaryVar; - public NetworkVariable> ULongSbyteDictionaryVar; - public NetworkVariable> Vector2SbyteDictionaryVar; - public NetworkVariable> HashMapKeyClassSbyteDictionaryVar; - - public NetworkVariable ShortVar; - public NetworkVariable> ShortArrayVar; - public NetworkVariable> ShortManagedListVar; - public NetworkVariable> ShortManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ShortListVar; - public NetworkVariable> ShortHashSetVar; - public NetworkVariable> ByteShortHashMapVar; - public NetworkVariable> ULongShortHashMapVar; - public NetworkVariable> Vector2ShortHashMapVar; - public NetworkVariable> HashMapKeyStructShortHashMapVar; -#endif - public NetworkVariable> ByteShortDictionaryVar; - public NetworkVariable> ULongShortDictionaryVar; - public NetworkVariable> Vector2ShortDictionaryVar; - public NetworkVariable> HashMapKeyClassShortDictionaryVar; - - public NetworkVariable UshortVar; - public NetworkVariable> UshortArrayVar; - public NetworkVariable> UshortManagedListVar; - public NetworkVariable> UshortManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UshortListVar; - public NetworkVariable> UshortHashSetVar; - public NetworkVariable> ByteUshortHashMapVar; - public NetworkVariable> ULongUshortHashMapVar; - public NetworkVariable> Vector2UshortHashMapVar; - public NetworkVariable> HashMapKeyStructUshortHashMapVar; -#endif - public NetworkVariable> ByteUshortDictionaryVar; - public NetworkVariable> ULongUshortDictionaryVar; - public NetworkVariable> Vector2UshortDictionaryVar; - public NetworkVariable> HashMapKeyClassUshortDictionaryVar; - - public NetworkVariable IntVar; - public NetworkVariable> IntArrayVar; - public NetworkVariable> IntManagedListVar; - public NetworkVariable> IntManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> IntListVar; - public NetworkVariable> IntHashSetVar; - public NetworkVariable> ByteIntHashMapVar; - public NetworkVariable> ULongIntHashMapVar; - public NetworkVariable> Vector2IntHashMapVar; - public NetworkVariable> HashMapKeyStructIntHashMapVar; -#endif - public NetworkVariable> ByteIntDictionaryVar; - public NetworkVariable> ULongIntDictionaryVar; - public NetworkVariable> Vector2IntDictionaryVar; - public NetworkVariable> HashMapKeyClassIntDictionaryVar; - - public NetworkVariable UintVar; - public NetworkVariable> UintArrayVar; - public NetworkVariable> UintManagedListVar; - public NetworkVariable> UintManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UintListVar; - public NetworkVariable> UintHashSetVar; - public NetworkVariable> ByteUintHashMapVar; - public NetworkVariable> ULongUintHashMapVar; - public NetworkVariable> Vector2UintHashMapVar; - public NetworkVariable> HashMapKeyStructUintHashMapVar; -#endif - public NetworkVariable> ByteUintDictionaryVar; - public NetworkVariable> ULongUintDictionaryVar; - public NetworkVariable> Vector2UintDictionaryVar; - public NetworkVariable> HashMapKeyClassUintDictionaryVar; - - public NetworkVariable LongVar; - public NetworkVariable> LongArrayVar; - public NetworkVariable> LongManagedListVar; - public NetworkVariable> LongManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> LongListVar; - public NetworkVariable> LongHashSetVar; - public NetworkVariable> ByteLongHashMapVar; - public NetworkVariable> ULongLongHashMapVar; - public NetworkVariable> Vector2LongHashMapVar; - public NetworkVariable> HashMapKeyStructLongHashMapVar; -#endif - public NetworkVariable> ByteLongDictionaryVar; - public NetworkVariable> ULongLongDictionaryVar; - public NetworkVariable> Vector2LongDictionaryVar; - public NetworkVariable> HashMapKeyClassLongDictionaryVar; - - public NetworkVariable UlongVar; - public NetworkVariable> UlongArrayVar; - public NetworkVariable> UlongManagedListVar; - public NetworkVariable> UlongManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UlongListVar; - public NetworkVariable> UlongHashSetVar; - public NetworkVariable> ByteUlongHashMapVar; - public NetworkVariable> ULongUlongHashMapVar; - public NetworkVariable> Vector2UlongHashMapVar; - public NetworkVariable> HashMapKeyStructUlongHashMapVar; -#endif - public NetworkVariable> ByteUlongDictionaryVar; - public NetworkVariable> ULongUlongDictionaryVar; - public NetworkVariable> Vector2UlongDictionaryVar; - public NetworkVariable> HashMapKeyClassUlongDictionaryVar; - - public NetworkVariable BoolVar; - public NetworkVariable> BoolArrayVar; - public NetworkVariable> BoolManagedListVar; - public NetworkVariable> BoolManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> BoolListVar; - public NetworkVariable> BoolHashSetVar; - public NetworkVariable> ByteBoolHashMapVar; - public NetworkVariable> ULongBoolHashMapVar; - public NetworkVariable> Vector2BoolHashMapVar; - public NetworkVariable> HashMapKeyStructBoolHashMapVar; -#endif - public NetworkVariable> ByteBoolDictionaryVar; - public NetworkVariable> ULongBoolDictionaryVar; - public NetworkVariable> Vector2BoolDictionaryVar; - public NetworkVariable> HashMapKeyClassBoolDictionaryVar; - - public NetworkVariable CharVar; - public NetworkVariable> CharArrayVar; - public NetworkVariable> CharManagedListVar; - public NetworkVariable> CharManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> CharListVar; - public NetworkVariable> CharHashSetVar; - public NetworkVariable> ByteCharHashMapVar; - public NetworkVariable> ULongCharHashMapVar; - public NetworkVariable> Vector2CharHashMapVar; - public NetworkVariable> HashMapKeyStructCharHashMapVar; -#endif - public NetworkVariable> ByteCharDictionaryVar; - public NetworkVariable> ULongCharDictionaryVar; - public NetworkVariable> Vector2CharDictionaryVar; - public NetworkVariable> HashMapKeyClassCharDictionaryVar; - - public NetworkVariable FloatVar; - public NetworkVariable> FloatArrayVar; - public NetworkVariable> FloatManagedListVar; - public NetworkVariable> FloatManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> FloatListVar; - public NetworkVariable> FloatHashSetVar; - public NetworkVariable> ByteFloatHashMapVar; - public NetworkVariable> ULongFloatHashMapVar; - public NetworkVariable> Vector2FloatHashMapVar; - public NetworkVariable> HashMapKeyStructFloatHashMapVar; -#endif - public NetworkVariable> ByteFloatDictionaryVar; - public NetworkVariable> ULongFloatDictionaryVar; - public NetworkVariable> Vector2FloatDictionaryVar; - public NetworkVariable> HashMapKeyClassFloatDictionaryVar; - - public NetworkVariable DoubleVar; - public NetworkVariable> DoubleArrayVar; - public NetworkVariable> DoubleManagedListVar; - public NetworkVariable> DoubleManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> DoubleListVar; - public NetworkVariable> DoubleHashSetVar; - public NetworkVariable> ByteDoubleHashMapVar; - public NetworkVariable> ULongDoubleHashMapVar; - public NetworkVariable> Vector2DoubleHashMapVar; - public NetworkVariable> HashMapKeyStructDoubleHashMapVar; -#endif - public NetworkVariable> ByteDoubleDictionaryVar; - public NetworkVariable> ULongDoubleDictionaryVar; - public NetworkVariable> Vector2DoubleDictionaryVar; - public NetworkVariable> HashMapKeyClassDoubleDictionaryVar; - - public NetworkVariable ByteEnumVar; - public NetworkVariable> ByteEnumArrayVar; - public NetworkVariable> ByteEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ByteEnumListVar; -#endif - public NetworkVariable SByteEnumVar; - public NetworkVariable> SByteEnumArrayVar; - public NetworkVariable> SByteEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> SByteEnumListVar; -#endif - public NetworkVariable ShortEnumVar; - public NetworkVariable> ShortEnumArrayVar; - public NetworkVariable> ShortEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ShortEnumListVar; -#endif - public NetworkVariable UShortEnumVar; - public NetworkVariable> UShortEnumArrayVar; - public NetworkVariable> UShortEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UShortEnumListVar; -#endif - public NetworkVariable IntEnumVar; - public NetworkVariable> IntEnumArrayVar; - public NetworkVariable> IntEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> IntEnumListVar; -#endif - public NetworkVariable UIntEnumVar; - public NetworkVariable> UIntEnumArrayVar; - public NetworkVariable> UIntEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UIntEnumListVar; -#endif - public NetworkVariable LongEnumVar; - public NetworkVariable> LongEnumArrayVar; - public NetworkVariable> LongEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> LongEnumListVar; -#endif - public NetworkVariable ULongEnumVar; - public NetworkVariable> ULongEnumArrayVar; - public NetworkVariable> ULongEnumManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ULongEnumListVar; -#endif - public NetworkVariable Vector2Var; - public NetworkVariable> Vector2ArrayVar; - public NetworkVariable> Vector2ManagedListVar; - public NetworkVariable> Vector2ManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Vector2ListVar; - public NetworkVariable> Vector2HashSetVar; - public NetworkVariable> ByteVector2HashMapVar; - public NetworkVariable> ULongVector2HashMapVar; - public NetworkVariable> Vector2Vector2HashMapVar; - public NetworkVariable> HashMapKeyStructVector2HashMapVar; -#endif - public NetworkVariable> ByteVector2DictionaryVar; - public NetworkVariable> ULongVector2DictionaryVar; - public NetworkVariable> Vector2Vector2DictionaryVar; - public NetworkVariable> HashMapKeyClassVector2DictionaryVar; - - public NetworkVariable Vector3Var; - public NetworkVariable> Vector3ArrayVar; - public NetworkVariable> Vector3ManagedListVar; - public NetworkVariable> Vector3ManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Vector3ListVar; - public NetworkVariable> Vector3HashSetVar; - public NetworkVariable> ByteVector3HashMapVar; - public NetworkVariable> ULongVector3HashMapVar; - public NetworkVariable> Vector2Vector3HashMapVar; - public NetworkVariable> HashMapKeyStructVector3HashMapVar; -#endif - public NetworkVariable> ByteVector3DictionaryVar; - public NetworkVariable> ULongVector3DictionaryVar; - public NetworkVariable> Vector2Vector3DictionaryVar; - public NetworkVariable> HashMapKeyClassVector3DictionaryVar; - - public NetworkVariable Vector2IntVar; - public NetworkVariable> Vector2IntArrayVar; - public NetworkVariable> Vector2IntManagedListVar; - public NetworkVariable> Vector2IntManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Vector2IntListVar; - public NetworkVariable> Vector2IntHashSetVar; - public NetworkVariable> ByteVector2IntHashMapVar; - public NetworkVariable> ULongVector2IntHashMapVar; - public NetworkVariable> Vector2Vector2IntHashMapVar; - public NetworkVariable> HashMapKeyStructVector2IntHashMapVar; -#endif - public NetworkVariable> ByteVector2IntDictionaryVar; - public NetworkVariable> ULongVector2IntDictionaryVar; - public NetworkVariable> Vector2Vector2IntDictionaryVar; - public NetworkVariable> HashMapKeyClassVector2IntDictionaryVar; - - public NetworkVariable Vector3IntVar; - public NetworkVariable> Vector3IntArrayVar; - public NetworkVariable> Vector3IntManagedListVar; - public NetworkVariable> Vector3IntManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Vector3IntListVar; - public NetworkVariable> Vector3IntHashSetVar; - public NetworkVariable> ByteVector3IntHashMapVar; - public NetworkVariable> ULongVector3IntHashMapVar; - public NetworkVariable> Vector2Vector3IntHashMapVar; - public NetworkVariable> HashMapKeyStructVector3IntHashMapVar; -#endif - public NetworkVariable> ByteVector3IntDictionaryVar; - public NetworkVariable> ULongVector3IntDictionaryVar; - public NetworkVariable> Vector2Vector3IntDictionaryVar; - public NetworkVariable> HashMapKeyClassVector3IntDictionaryVar; - - public NetworkVariable Vector4Var; - public NetworkVariable> Vector4ArrayVar; - public NetworkVariable> Vector4ManagedListVar; - public NetworkVariable> Vector4ManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Vector4ListVar; - public NetworkVariable> Vector4HashSetVar; - public NetworkVariable> ByteVector4HashMapVar; - public NetworkVariable> ULongVector4HashMapVar; - public NetworkVariable> Vector2Vector4HashMapVar; - public NetworkVariable> HashMapKeyStructVector4HashMapVar; -#endif - public NetworkVariable> ByteVector4DictionaryVar; - public NetworkVariable> ULongVector4DictionaryVar; - public NetworkVariable> Vector2Vector4DictionaryVar; - public NetworkVariable> HashMapKeyClassVector4DictionaryVar; - - public NetworkVariable QuaternionVar; - public NetworkVariable> QuaternionArrayVar; - public NetworkVariable> QuaternionManagedListVar; - public NetworkVariable> QuaternionManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> QuaternionListVar; - public NetworkVariable> QuaternionHashSetVar; - public NetworkVariable> ByteQuaternionHashMapVar; - public NetworkVariable> ULongQuaternionHashMapVar; - public NetworkVariable> Vector2QuaternionHashMapVar; - public NetworkVariable> HashMapKeyStructQuaternionHashMapVar; -#endif - public NetworkVariable> ByteQuaternionDictionaryVar; - public NetworkVariable> ULongQuaternionDictionaryVar; - public NetworkVariable> Vector2QuaternionDictionaryVar; - public NetworkVariable> HashMapKeyClassQuaternionDictionaryVar; - - public NetworkVariable ColorVar; - public NetworkVariable> ColorArrayVar; - public NetworkVariable> ColorManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> ColorListVar; -#endif - public NetworkVariable Color32Var; - public NetworkVariable> Color32ArrayVar; - public NetworkVariable> Color32ManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Color32ListVar; -#endif - public NetworkVariable RayVar; - public NetworkVariable> RayArrayVar; - public NetworkVariable> RayManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> RayListVar; -#endif - public NetworkVariable Ray2DVar; - public NetworkVariable> Ray2DArrayVar; - public NetworkVariable> Ray2DManagedListVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> Ray2DListVar; -#endif - public NetworkVariable TestStructVar; - public NetworkVariable> TestStructArrayVar; - public NetworkVariable> TestStructManagedListVar; - public NetworkVariable> TestStructManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> TestStructListVar; - public NetworkVariable> TestStructHashSetVar; - public NetworkVariable> ByteTestStructHashMapVar; - public NetworkVariable> ULongTestStructHashMapVar; - public NetworkVariable> Vector2TestStructHashMapVar; - public NetworkVariable> HashMapKeyStructTestStructHashMapVar; -#endif - public NetworkVariable> ByteTestStructDictionaryVar; - public NetworkVariable> ULongTestStructDictionaryVar; - public NetworkVariable> Vector2TestStructDictionaryVar; - public NetworkVariable> HashMapKeyClassTestStructDictionaryVar; - - - public NetworkVariable FixedStringVar; - public NetworkVariable> FixedStringArrayVar; - public NetworkVariable> FixedStringManagedListVar; - public NetworkVariable> FixedStringManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> FixedStringListVar; - public NetworkVariable> FixedStringHashSetVar; - public NetworkVariable> ByteFixedStringHashMapVar; - public NetworkVariable> ULongFixedStringHashMapVar; - public NetworkVariable> Vector2FixedStringHashMapVar; - public NetworkVariable> HashMapKeyStructFixedStringHashMapVar; -#endif - public NetworkVariable> ByteFixedStringDictionaryVar; - public NetworkVariable> ULongFixedStringDictionaryVar; - public NetworkVariable> Vector2FixedStringDictionaryVar; - public NetworkVariable> HashMapKeyClassFixedStringDictionaryVar; - - - public NetworkVariable UnmanagedNetworkSerializableTypeVar; - public NetworkVariable> UnmanagedNetworkSerializableManagedHashSetVar; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public NetworkVariable> UnmanagedNetworkSerializableListVar; - public NetworkVariable> UnmanagedNetworkSerializableHashSetVar; - public NetworkVariable> ByteUnmanagedNetworkSerializableHashMapVar; - public NetworkVariable> ULongUnmanagedNetworkSerializableHashMapVar; - public NetworkVariable> Vector2UnmanagedNetworkSerializableHashMapVar; - public NetworkVariable> HashMapKeyStructUnmanagedNetworkSerializableHashMapVar; -#endif - public NetworkVariable> ByteUnmanagedNetworkSerializableDictionaryVar; - public NetworkVariable> ULongUnmanagedNetworkSerializableDictionaryVar; - public NetworkVariable> Vector2UnmanagedNetworkSerializableDictionaryVar; - public NetworkVariable> HashMapKeyClassUnmanagedNetworkSerializableDictionaryVar; - - public NetworkVariable> UnmanagedNetworkSerializableArrayVar; - public NetworkVariable> UnmanagedNetworkSerializableManagedListVar; - - public NetworkVariable ManagedNetworkSerializableTypeVar; - - public NetworkVariable StringVar; - public NetworkVariable GuidVar; - public NetworkVariableSubclass> SubclassVar; - } - - internal class TemplateNetworkBehaviourType : NetworkBehaviour - { - public NetworkVariable TheVar; - } - - internal class IntermediateNetworkBehavior : TemplateNetworkBehaviourType - { - public NetworkVariable TheVar2; - } -#if !NGO_MINIMALPROJECT - internal class ClassHavingNetworkBehaviour : IntermediateNetworkBehavior - { - - } - - // Please do not reference TestClass_ReferencedOnlyByTemplateNetworkBehavourType anywhere other than here! - internal class ClassHavingNetworkBehaviour2 : TemplateNetworkBehaviourType - { - - } - - internal class StructHavingNetworkBehaviour : TemplateNetworkBehaviourType - { - - } -#endif - - internal struct StructUsedOnlyInNetworkList : IEquatable, INetworkSerializeByMemcpy - { - public int Value; - - public bool Equals(StructUsedOnlyInNetworkList other) - { - return Value == other.Value; - } - - public override bool Equals(object obj) - { - return obj is StructUsedOnlyInNetworkList other && Equals(other); - } - - public override int GetHashCode() - { - return Value; - } - } - -} diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs.meta deleted file mode 100644 index c71cb92..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTestsHelperTypes.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a580aaafc247486193f372174a99fae4 -timeCreated: 1705098783 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs deleted file mode 100644 index 66c326c..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkVariableTraitsComponent : NetworkBehaviour - { - public NetworkVariable TheVariable = new NetworkVariable(); - } - - internal class NetworkVariableTraitsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected override void OnPlayerPrefabGameObjectCreated() - { - m_PlayerPrefab.AddComponent(); - } - - public NetworkVariableTraitsComponent GetTestComponent() - { - return m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - } - - public NetworkVariableTraitsComponent GetServerComponent() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.NetworkManager == m_ServerNetworkManager && obj.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId) - { - return obj; - } - } - - return null; - } - - [Test] - public void WhenNewValueIsLessThanThreshold_VariableIsNotSerialized() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; - - serverComponent.TheVariable.Value = 0.05f; - - TimeTravel(2, 120); - - Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0, testComponent.TheVariable.Value); ; - } - [Test] - public void WhenNewValueIsGreaterThanThreshold_VariableIsSerialized() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; - - serverComponent.TheVariable.Value = 0.15f; - - TimeTravel(2, 120); - - Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ; - } - - [Test] - public void WhenNewValueIsLessThanThresholdButMaxTimeHasPassed_VariableIsSerialized() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; - serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MaxSecondsBetweenUpdates = 2 }); - serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime; - - serverComponent.TheVariable.Value = 0.05f; - - TimeTravel(1 / 60f * 119, 119); - - Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0, testComponent.TheVariable.Value); ; - - TimeTravel(1 / 60f * 4, 4); - - Assert.AreEqual(0.05f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0.05f, testComponent.TheVariable.Value); ; - } - - [Test] - public void WhenNewValueIsGreaterThanThresholdButMinTimeHasNotPassed_VariableIsNotSerialized() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - serverComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; - serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 2 }); - serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime; - - serverComponent.TheVariable.Value = 0.15f; - - TimeTravel(1 / 60f * 119, 119); - - Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0, testComponent.TheVariable.Value); ; - - TimeTravel(1 / 60f * 4, 4); - - Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ; - } - - [Test] - public void WhenNoThresholdIsSetButMinTimeHasNotPassed_VariableIsNotSerialized() - { - var serverComponent = GetServerComponent(); - var testComponent = GetTestComponent(); - serverComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 2 }); - serverComponent.TheVariable.LastUpdateSent = m_ServerNetworkManager.NetworkTimeSystem.LocalTime; - - serverComponent.TheVariable.Value = 0.15f; - - TimeTravel(1 / 60f * 119, 119); - - Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0, testComponent.TheVariable.Value); ; - - TimeTravel(1 / 60f * 4, 4); - - Assert.AreEqual(0.15f, serverComponent.TheVariable.Value); ; - Assert.AreEqual(0.15f, testComponent.TheVariable.Value); ; - } - } -} diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs.meta deleted file mode 100644 index 3bfb25d..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 49f46ca2b4327464498a7465891647bb \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs b/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs deleted file mode 100644 index c261bdf..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - internal struct MyTypeOne - { - public int Value; - } - internal struct MyTypeTwo - { - public int Value; - } - internal struct MyTypeThree - { - public int Value; - } - - /// - /// Used to help track instances of any child derived class - /// - internal class WorkingUserNetworkVariableComponentBase : NetworkBehaviour - { - private static Dictionary s_Instances = new Dictionary(); - - internal static T GetRelativeInstance(ulong clientId) where T : NetworkBehaviour - { - if (s_Instances.ContainsKey(clientId)) - { - return s_Instances[clientId] as T; - } - return null; - } - - public static void Reset() - { - s_Instances.Clear(); - } - - public override void OnNetworkSpawn() - { - if (!s_Instances.ContainsKey(NetworkManager.LocalClientId)) - { - s_Instances.Add(NetworkManager.LocalClientId, this); - } - else - { - Debug.LogWarning($"{name} is spawned but client id {NetworkManager.LocalClientId} instance already exists!"); - } - } - - public override void OnNetworkDespawn() - { - if (s_Instances.ContainsKey(NetworkManager.LocalClientId)) - { - s_Instances.Remove(NetworkManager.LocalClientId); - } - else - { - Debug.LogWarning($"{name} is was never spawned but client id {NetworkManager.LocalClientId} is trying to despawn it!"); - } - } - } - - internal class WorkingUserNetworkVariableComponent : WorkingUserNetworkVariableComponentBase - { - public NetworkVariable NetworkVariable = new NetworkVariable(); - } - - internal class WorkingUserNetworkVariableComponentUsingExtensionMethod : WorkingUserNetworkVariableComponentBase - { - public NetworkVariable NetworkVariable = new NetworkVariable(); - } - internal class NonWorkingUserNetworkVariableComponent : NetworkBehaviour - { - public NetworkVariable NetworkVariable = new NetworkVariable(); - } - - internal static class NetworkVariableUserSerializableTypesTestsExtensionMethods - { - public static void WriteValueSafe(this FastBufferWriter writer, in MyTypeTwo value) - { - writer.WriteValueSafe(value.Value); - } - - public static void ReadValueSafe(this FastBufferReader reader, out MyTypeTwo value) - { - value = new MyTypeTwo(); - reader.ReadValueSafe(out value.Value); - } - } - - internal class NetworkVariableUserSerializableTypesTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - public NetworkVariableUserSerializableTypesTests() - : base(HostOrServer.Server) - { - } - - private GameObject m_WorkingPrefab; - private GameObject m_ExtensionMethodPrefab; - private GameObject m_NonWorkingPrefab; - - protected override IEnumerator OnSetup() - { - WorkingUserNetworkVariableComponentBase.Reset(); - - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - UserNetworkVariableSerialization.WriteValue = null; - UserNetworkVariableSerialization.ReadValue = null; - UserNetworkVariableSerialization.DuplicateValue = null; - return base.OnSetup(); - } - - protected override void OnServerAndClientsCreated() - { - m_WorkingPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_WorkingPrefab)}]"); - m_ExtensionMethodPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_ExtensionMethodPrefab)}]"); - m_NonWorkingPrefab = CreateNetworkObjectPrefab($"[{nameof(NetworkVariableUserSerializableTypesTests)}.{nameof(m_NonWorkingPrefab)}]"); - m_WorkingPrefab.AddComponent(); - m_ExtensionMethodPrefab.AddComponent(); - m_NonWorkingPrefab.AddComponent(); - } - - private bool CheckForClientInstance() where T : WorkingUserNetworkVariableComponentBase - { - var instance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance(m_ClientNetworkManagers[0].LocalClientId); - return instance != null && instance.IsSpawned; - } - - [UnityTest] - public IEnumerator WhenUsingAUserSerializableNetworkVariableWithUserSerialization_ReplicationWorks() - { - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in MyTypeOne value) => - { - writer.WriteValueSafe(value.Value); - }; - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out MyTypeOne value) => - { - value = new MyTypeOne(); - reader.ReadValueSafe(out value.Value); - }; - UserNetworkVariableSerialization.DuplicateValue = (in MyTypeOne value, ref MyTypeOne duplicatedValue) => - { - duplicatedValue = value; - }; - - var serverObject = SpawnObject(m_WorkingPrefab, m_ServerNetworkManager); - var serverNetworkObject = serverObject.GetComponent(); - - // Wait for the client instance to be spawned, which removes the need to check for two NetworkVariableDeltaMessages - yield return WaitForConditionOrTimeOut(() => CheckForClientInstance()); - AssertOnTimeout($"Timed out waiting for the client side object to spawn!"); - - // Get server and client instances of the test component - var clientInstance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance(m_ClientNetworkManagers[0].LocalClientId); - var serverInstance = serverNetworkObject.GetComponent(); - - // Set the server side value - serverInstance.NetworkVariable.Value = new MyTypeOne { Value = 20 }; - - // Wait for the NetworkVariableDeltaMessage - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - - // Wait for the client side value to be updated to the server side value (can take an additional frame) - yield return WaitForConditionOrTimeOut(() => clientInstance.NetworkVariable.Value.Value == serverInstance.NetworkVariable.Value.Value); - Assert.AreEqual(serverNetworkObject.GetComponent().NetworkVariable.Value.Value, clientInstance.NetworkVariable.Value.Value); - Assert.AreEqual(20, clientInstance.NetworkVariable.Value.Value); - } - - [UnityTest] - public IEnumerator WhenUsingAUserSerializableNetworkVariableWithUserSerializationViaExtensionMethod_ReplicationWorks() - { - UserNetworkVariableSerialization.WriteValue = NetworkVariableUserSerializableTypesTestsExtensionMethods.WriteValueSafe; - UserNetworkVariableSerialization.ReadValue = NetworkVariableUserSerializableTypesTestsExtensionMethods.ReadValueSafe; - UserNetworkVariableSerialization.DuplicateValue = (in MyTypeTwo value, ref MyTypeTwo duplicatedValue) => - { - duplicatedValue = value; - }; - - var serverObject = SpawnObject(m_ExtensionMethodPrefab, m_ServerNetworkManager); - var serverNetworkObject = serverObject.GetComponent(); - - // Wait for the client instance to be spawned, which removes the need to check for two NetworkVariableDeltaMessages - yield return WaitForConditionOrTimeOut(() => CheckForClientInstance()); - AssertOnTimeout($"Timed out waiting for the client side object to spawn!"); - - // Get server and client instances of the test component - var clientInstance = WorkingUserNetworkVariableComponentBase.GetRelativeInstance(m_ClientNetworkManagers[0].LocalClientId); - var serverInstance = serverNetworkObject.GetComponent(); - // Set the server side value - serverInstance.NetworkVariable.Value = new MyTypeTwo { Value = 20 }; - - // Wait for the NetworkVariableDeltaMessage - yield return NetcodeIntegrationTestHelpers.WaitForMessageOfTypeReceived(m_ClientNetworkManagers[0]); - - // Wait for the client side value to be updated to the server side value (can take an additional frame) - yield return WaitForConditionOrTimeOut(() => clientInstance.NetworkVariable.Value.Value == serverInstance.NetworkVariable.Value.Value); - AssertOnTimeout($"Timed out waiting for the client side object's value ({clientInstance.NetworkVariable.Value.Value}) to equal the server side objects value ({serverInstance.NetworkVariable.Value.Value})!"); - Assert.AreEqual(serverInstance.NetworkVariable.Value.Value, clientInstance.NetworkVariable.Value.Value); - Assert.AreEqual(20, clientInstance.NetworkVariable.Value.Value); - } - - [Test] - public void WhenUsingAUserSerializableNetworkVariableWithoutUserSerialization_ReplicationFails() - { - var serverObject = Object.Instantiate(m_NonWorkingPrefab); - var serverNetworkObject = serverObject.GetComponent(); - serverNetworkObject.NetworkManagerOwner = m_ServerNetworkManager; - Assert.Throws( - () => - { - serverNetworkObject.Spawn(); - } - ); - } - - protected override IEnumerator OnTearDown() - { - // These have to get set to SOMETHING, otherwise we will get an exception thrown because Object.Destroy() - // calls __initializeNetworkVariables, and the network variable initialization attempts to call FallbackSerializer, - // which throws an exception if any of these values are null. They don't have to DO anything, they just have to - // be non-null to keep the test from failing during teardown. - // None of this is related to what's being tested above, and in reality, these values being null is an invalid - // use case. But one of the tests is explicitly testing that invalid use case, and the values are being set - // to null in OnSetup to ensure test isolation. This wouldn't be a situation a user would have to think about - // in a real world use case. - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in MyTypeOne value) => { }; - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out MyTypeOne value) => { value = new MyTypeOne(); }; - UserNetworkVariableSerialization.DuplicateValue = (in MyTypeOne value, ref MyTypeOne duplicatedValue) => - { - duplicatedValue = value; - }; - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in MyTypeTwo value) => { }; - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out MyTypeTwo value) => { value = new MyTypeTwo(); }; - UserNetworkVariableSerialization.DuplicateValue = (in MyTypeTwo value, ref MyTypeTwo duplicatedValue) => - { - duplicatedValue = value; - }; - UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in MyTypeThree value) => { }; - UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out MyTypeThree value) => { value = new MyTypeThree(); }; - UserNetworkVariableSerialization.DuplicateValue = (in MyTypeThree value, ref MyTypeThree duplicatedValue) => - { - duplicatedValue = value; - }; - return base.OnTearDown(); - } - } -} - diff --git a/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs.meta b/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs.meta deleted file mode 100644 index a5c7fa3..0000000 --- a/Tests/Runtime/NetworkVariable/NetworkVariableUserSerializableTypesTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a1195640cf744e85b58c5af6d11eeb34 -timeCreated: 1652907276 \ No newline at end of file diff --git a/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs b/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs deleted file mode 100644 index 3a925b9..0000000 --- a/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - // This is a bit of a quirky test. - // Addresses MTT-4386 #2109 - // Where the NetworkVariable updates would be repeated on some clients. - // The twist comes fom the updates needing to happens very specifically for the issue to repro in tests - - internal class OwnerModifiedObject : NetworkBehaviour, INetworkUpdateSystem - { - public NetworkList MyNetworkList; - - internal static int Updates = 0; - - public static bool EnableVerbose; - - private void Awake() - { - MyNetworkList = new NetworkList(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - MyNetworkList.OnListChanged += Changed; - } - - public void Changed(NetworkListEvent listEvent) - { - var expected = 0; - var listString = ""; - foreach (var i in MyNetworkList) - { - Assert.AreEqual(i, expected); - expected++; - listString += i.ToString(); - } - if (EnableVerbose) - { - Debug.Log($"[{NetworkManager.LocalClientId}] Value changed to {listString}"); - } - - Updates++; - } - - public bool AddValues; - - public NetworkUpdateStage NetworkUpdateStageToCheck; - - private int m_ValueToUpdate; - - public void NetworkUpdate(NetworkUpdateStage updateStage) - { - if (updateStage == NetworkUpdateStageToCheck) - { - if (AddValues) - { - MyNetworkList.Add(m_ValueToUpdate++); - AddValues = false; - } - } - } - - public override void OnDestroy() - { - NetworkUpdateLoop.UnregisterAllNetworkUpdates(this); - base.OnDestroy(); - } - - public void InitializeLastCient() - { - NetworkUpdateLoop.RegisterAllNetworkUpdates(this); - } - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - internal class OwnerModifiedTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - public OwnerModifiedTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - [UnityTest] - public IEnumerator OwnerModifiedTest() - { - OwnerModifiedObject.EnableVerbose = m_EnableVerboseDebug; - // We use this to assure we are the "last client" connected. - yield return CreateAndStartNewClient(); - var ownerModLastClient = m_ClientNetworkManagers[2].LocalClient.PlayerObject.GetComponent(); - ownerModLastClient.InitializeLastCient(); - - // Run through all update loops setting the value once every 5 frames - foreach (var updateLoopType in System.Enum.GetValues(typeof(NetworkUpdateStage))) - { - ownerModLastClient.NetworkUpdateStageToCheck = (NetworkUpdateStage)updateLoopType; - VerboseDebug($"Testing Update Stage: {ownerModLastClient.NetworkUpdateStageToCheck}"); - ownerModLastClient.AddValues = true; - yield return WaitForTicks(m_ServerNetworkManager, 5); - } - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // We'll have at least one update per stage per client, if all goes well. - Assert.True(OwnerModifiedObject.Updates > 20); - } - } -} diff --git a/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs.meta b/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs.meta deleted file mode 100644 index 700bc20..0000000 --- a/Tests/Runtime/NetworkVariable/OwnerModifiedTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 419d83ebac7544ea9b0a9d5c3eab2c71 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs b/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs deleted file mode 100644 index 01878e1..0000000 --- a/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class OwnerPermissionObject : NetworkBehaviour - { - // indexed by [object, machine] - public static OwnerPermissionObject[,] Objects = new OwnerPermissionObject[3, 3]; - public static int CurrentlySpawning = 0; - - public static List ClientTargetedNetworkObjects = new List(); - // a client-owned NetworkVariable - public NetworkVariable MyNetworkVariableOwner; - // a server-owned NetworkVariable - public NetworkVariable MyNetworkVariableServer; - - // a client-owned NetworkVariable - public NetworkList MyNetworkListOwner; - // a server-owned NetworkVariable - public NetworkList MyNetworkListServer; - - // verifies two lists are identical - public static void CheckLists(NetworkList listA, NetworkList listB) - { - Debug.Assert(listA.Count == listB.Count); - for (var i = 0; i < listA.Count; i++) - { - Debug.Assert(listA[i] == listB[i]); - } - } - - // verifies all objects have consistent lists on all clients - public static void VerifyConsistency() - { - for (var objectIndex = 0; objectIndex < 3; objectIndex++) - { - CheckLists(Objects[objectIndex, 0].MyNetworkListOwner, Objects[objectIndex, 1].MyNetworkListOwner); - CheckLists(Objects[objectIndex, 0].MyNetworkListOwner, Objects[objectIndex, 2].MyNetworkListOwner); - - CheckLists(Objects[objectIndex, 0].MyNetworkListServer, Objects[objectIndex, 1].MyNetworkListServer); - CheckLists(Objects[objectIndex, 0].MyNetworkListServer, Objects[objectIndex, 2].MyNetworkListServer); - } - } - - public override void OnNetworkSpawn() - { - Objects[CurrentlySpawning, NetworkManager.LocalClientId] = GetComponent(); - } - - private void Awake() - { - MyNetworkVariableOwner = new NetworkVariable(writePerm: NetworkVariableWritePermission.Owner); - MyNetworkVariableOwner.OnValueChanged += OwnerChanged; - - MyNetworkVariableServer = new NetworkVariable(writePerm: NetworkVariableWritePermission.Server); - MyNetworkVariableServer.OnValueChanged += ServerChanged; - - MyNetworkListOwner = new NetworkList(writePerm: NetworkVariableWritePermission.Owner); - MyNetworkListOwner.OnListChanged += ListOwnerChanged; - - MyNetworkListServer = new NetworkList(writePerm: NetworkVariableWritePermission.Server); - MyNetworkListServer.OnListChanged += ListServerChanged; - } - - public void OwnerChanged(int before, int after) - { - } - - public void ServerChanged(int before, int after) - { - } - - public void ListOwnerChanged(NetworkListEvent listEvent) - { - } - - public void ListServerChanged(NetworkListEvent listEvent) - { - } - } - - - - internal class OwnerPermissionHideTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - private GameObject m_PrefabToSpawn; - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("OwnerPermissionObject"); - m_PrefabToSpawn.AddComponent(); - } - - [UnityTest] - public IEnumerator OwnerPermissionTest() - { - // create 3 objects - for (var objectIndex = 0; objectIndex < 3; objectIndex++) - { - OwnerPermissionObject.CurrentlySpawning = objectIndex; - - NetworkManager ownerManager = m_ServerNetworkManager; - if (objectIndex != 0) - { - ownerManager = m_ClientNetworkManagers[objectIndex - 1]; - } - SpawnObject(m_PrefabToSpawn, ownerManager); - - // wait for each object to spawn on each client - for (var clientIndex = 0; clientIndex < 3; clientIndex++) - { - while (OwnerPermissionObject.Objects[objectIndex, clientIndex] == null) - { - yield return new WaitForSeconds(0.0f); - } - } - } - - var nextValueToWrite = 1; - var serverIndex = 0; - - for (var objectIndex = 0; objectIndex < 3; objectIndex++) - { - for (var clientWriting = 0; clientWriting < 3; clientWriting++) - { - // ==== Server-writable NetworkVariable ==== - VerboseDebug($"Writing to server-write variable on object {objectIndex} on client {clientWriting}"); - - nextValueToWrite++; - if (clientWriting != serverIndex) - { - LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.GetWritePermissionError()); - } - OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableServer.Value = nextValueToWrite; - - // ==== Owner-writable NetworkVariable ==== - VerboseDebug($"Writing to owner-write variable on object {objectIndex} on client {clientWriting}"); - - nextValueToWrite++; - if (clientWriting != objectIndex) - { - LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.GetWritePermissionError()); - } - OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkVariableOwner.Value = nextValueToWrite; - - // ==== Server-writable NetworkList ==== - VerboseDebug($"Writing to [Add] server-write NetworkList on object {objectIndex} on client {clientWriting}"); - - nextValueToWrite++; - if (clientWriting != serverIndex) - { - LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.GetWritePermissionError()); - } - OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListServer.Add(nextValueToWrite); - - // ==== Owner-writable NetworkList ==== - VerboseDebug($"Writing to [Add] owner-write NetworkList on object {objectIndex} on client {clientWriting}"); - - nextValueToWrite++; - if (clientWriting != objectIndex) - { - LogAssert.Expect(LogType.Error, OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.GetWritePermissionError()); - } - OwnerPermissionObject.Objects[objectIndex, clientWriting].MyNetworkListOwner.Add(nextValueToWrite); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - yield return WaitForTicks(m_ClientNetworkManagers[0], 5); - yield return WaitForTicks(m_ClientNetworkManagers[1], 5); - - OwnerPermissionObject.VerifyConsistency(); - } - } - } - } -} diff --git a/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs.meta b/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs.meta deleted file mode 100644 index a7d90d5..0000000 --- a/Tests/Runtime/NetworkVariable/OwnerPermissionTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 88c657dcbe9a2414ba551b60dab19acd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/NetworkVisibilityTests.cs b/Tests/Runtime/NetworkVisibilityTests.cs deleted file mode 100644 index a19f856..0000000 --- a/Tests/Runtime/NetworkVisibilityTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(SceneManagementState.SceneManagementEnabled, NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(SceneManagementState.SceneManagementDisabled, NetworkTopologyTypes.DistributedAuthority)] - [TestFixture(SceneManagementState.SceneManagementEnabled, NetworkTopologyTypes.ClientServer)] - [TestFixture(SceneManagementState.SceneManagementDisabled, NetworkTopologyTypes.ClientServer)] - internal class NetworkVisibilityTests : NetcodeIntegrationTest - { - - protected override int NumberOfClients => 2; - private GameObject m_TestNetworkPrefab; - private bool m_SceneManagementEnabled; - private GameObject m_SpawnedObject; - private NetworkManager m_SessionOwner; - - public NetworkVisibilityTests(SceneManagementState sceneManagementState, NetworkTopologyTypes networkTopologyType) : base(networkTopologyType) - { - m_SceneManagementEnabled = sceneManagementState == SceneManagementState.SceneManagementEnabled; - } - - protected override void OnServerAndClientsCreated() - { - m_TestNetworkPrefab = CreateNetworkObjectPrefab("Object"); - m_TestNetworkPrefab.AddComponent(); - if (!UseCMBService()) - { - m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_SceneManagementEnabled; - } - - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - clientNetworkManager.NetworkConfig.EnableSceneManagement = m_SceneManagementEnabled; - } - base.OnServerAndClientsCreated(); - } - - - protected override IEnumerator OnServerAndClientsConnected() - { - m_SessionOwner = UseCMBService() ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - m_SpawnedObject = SpawnObject(m_TestNetworkPrefab, m_SessionOwner); - - yield return base.OnServerAndClientsConnected(); - } - - [UnityTest] - public IEnumerator HiddenObjectsTest() - { - var expectedCount = UseCMBService() ? 2 : 3; -#if UNITY_2023_1_OR_NEWER - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == expectedCount); -#else - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType().Where((c) => c.IsSpawned).Count() == expectedCount); -#endif - - Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for the visible object count to equal 2!"); - } - - [UnityTest] - public IEnumerator HideShowAndDeleteTest() - { - var expectedCount = UseCMBService() ? 2 : 3; -#if UNITY_2023_1_OR_NEWER - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == expectedCount); -#else - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType().Where((c) => c.IsSpawned).Count() == expectedCount); -#endif - AssertOnTimeout("Timed out waiting for the visible object count to equal 2!"); - - var sessionOwnerNetworkObject = m_SpawnedObject.GetComponent(); - var clientIndex = UseCMBService() ? 1 : 0; - sessionOwnerNetworkObject.NetworkHide(m_ClientNetworkManagers[clientIndex].LocalClientId); -#if UNITY_2023_1_OR_NEWER - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == expectedCount - 1); -#else - yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType().Where((c) => c.IsSpawned).Count() == expectedCount - 1); -#endif - AssertOnTimeout($"Timed out waiting for {m_SpawnedObject.name} to be hidden from client!"); - var networkObjectId = sessionOwnerNetworkObject.NetworkObjectId; - sessionOwnerNetworkObject.NetworkShow(m_ClientNetworkManagers[clientIndex].LocalClientId); - sessionOwnerNetworkObject.Despawn(true); - - // Expect no exceptions - yield return s_DefaultWaitForTick; - - // Now force a scenario where it normally would have caused an exception - m_SessionOwner.SpawnManager.ObjectsToShowToClient.Add(m_ClientNetworkManagers[clientIndex].LocalClientId, new System.Collections.Generic.List()); - m_SessionOwner.SpawnManager.ObjectsToShowToClient[m_ClientNetworkManagers[clientIndex].LocalClientId].Add(null); - - // Expect no exceptions - yield return s_DefaultWaitForTick; - } - } -} diff --git a/Tests/Runtime/NetworkVisibilityTests.cs.meta b/Tests/Runtime/NetworkVisibilityTests.cs.meta deleted file mode 100644 index 3747caf..0000000 --- a/Tests/Runtime/NetworkVisibilityTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 45ff8252bf32540509fde11c19e0f3c2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/PeerDisconnectCallbackTests.cs b/Tests/Runtime/PeerDisconnectCallbackTests.cs deleted file mode 100644 index 896aa90..0000000 --- a/Tests/Runtime/PeerDisconnectCallbackTests.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Validates the client disconnection process. - /// This assures that: - /// - When a client disconnects from the server that the server: - /// -- Detects the client disconnected. - /// -- Cleans up the transport to NGO client (and vice versa) mappings. - /// - When a server disconnects a client that: - /// -- The client detects this disconnection. - /// -- The server cleans up the transport to NGO client (and vice versa) mappings. - /// - When the server-side player object is destroyed - /// - When the server-side player object ownership is transferred back to the server - /// - [TestFixture(HostOrServer.Server)] - [TestFixture(HostOrServer.Host)] - internal class PeerDisconnectCallbackTests : NetcodeIntegrationTest - { - - public enum ClientDisconnectType - { - ServerDisconnectsClient, - ClientDisconnectsFromServer - } - - protected override int NumberOfClients => 3; - - private int m_ClientDisconnectCount; - private int m_PeerDisconnectCount; - - - public PeerDisconnectCallbackTests(HostOrServer hostOrServer) - : base(hostOrServer) - { - } - - protected override void OnServerAndClientsCreated() - { - // Adjusting client and server timeout periods to reduce test time - // Get the tick frequency in milliseconds and triple it for the heartbeat timeout - var heartBeatTimeout = (int)(300 * (1.0f / m_ServerNetworkManager.NetworkConfig.TickRate)); - var unityTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport; - if (unityTransport != null) - { - unityTransport.HeartbeatTimeoutMS = heartBeatTimeout; - } - - unityTransport = m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport as Transports.UTP.UnityTransport; - if (unityTransport != null) - { - unityTransport.HeartbeatTimeoutMS = heartBeatTimeout; - } - - base.OnServerAndClientsCreated(); - } - - protected override IEnumerator OnSetup() - { - m_ClientDisconnectCount = 0; - m_PeerDisconnectCount = 0; - return base.OnSetup(); - } - - private void OnConnectionEventCallback(NetworkManager networkManager, ConnectionEventData data) - { - switch (data.EventType) - { - case ConnectionEvent.ClientDisconnected: - Assert.IsFalse(data.PeerClientIds.IsCreated); - ++m_ClientDisconnectCount; - break; - case ConnectionEvent.PeerDisconnected: - Assert.IsFalse(data.PeerClientIds.IsCreated); - ++m_PeerDisconnectCount; - break; - } - } - - [UnityTest] - public IEnumerator TestPeerDisconnectCallback([Values] ClientDisconnectType clientDisconnectType, [Values(1ul, 2ul, 3ul)] ulong disconnectedClient) - { - foreach (var client in m_ClientNetworkManagers) - { - client.OnConnectionEvent += OnConnectionEventCallback; - if (m_UseHost) - { - Assert.IsTrue(client.ConnectedClientsIds.Contains(0ul)); - } - Assert.IsTrue(client.ConnectedClientsIds.Contains(1ul)); - Assert.IsTrue(client.ConnectedClientsIds.Contains(2ul)); - Assert.IsTrue(client.ConnectedClientsIds.Contains(3ul)); - Assert.AreEqual(client.ServerIsHost, m_UseHost); - } - m_ServerNetworkManager.OnConnectionEvent += OnConnectionEventCallback; - if (m_UseHost) - { - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(0ul)); - } - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(1ul)); - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(2ul)); - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(3ul)); - Assert.AreEqual(m_ServerNetworkManager.ServerIsHost, m_UseHost); - - // Set up a WaitForMessageReceived hook. - // In some cases the message will be received during StopOneClient, but it is not guaranteed - // So we start the listener before we call Stop so it will be noticed regardless of whether it happens - // during StopOneClient or whether we have to wait for it - var messageHookEntriesForSpawn = new List(); - foreach (var clientNetworkManager in m_ClientNetworkManagers.Where(c => c.LocalClientId != disconnectedClient)) - { - var messageHook = new MessageHookEntry(clientNetworkManager); - messageHook.AssignMessageType(); - messageHookEntriesForSpawn.Add(messageHook); - } - - // Used to determine if all clients received the CreateObjectMessage - var hooks = new MessageHooksConditional(messageHookEntriesForSpawn); - - if (clientDisconnectType == ClientDisconnectType.ServerDisconnectsClient) - { - m_ServerNetworkManager.DisconnectClient(disconnectedClient); - } - else - { - yield return StopOneClient(m_ClientNetworkManagers[disconnectedClient - 1]); - } - - yield return WaitForConditionOrTimeOut(hooks); - - Assert.False(s_GlobalTimeoutHelper.TimedOut); - - foreach (var client in m_ClientNetworkManagers) - { - if (!client.IsConnectedClient) - { - Assert.IsEmpty(client.ConnectedClientsIds); - continue; - } - if (m_UseHost) - { - Assert.IsTrue(client.ConnectedClientsIds.Contains(0ul), $"[Client-{client.LocalClientId}][Connected ({client.IsConnectedClient})] Still has client identifier 0!"); - } - - for (var i = 1ul; i < 3ul; ++i) - { - if (i == disconnectedClient) - { - Assert.IsFalse(client.ConnectedClientsIds.Contains(i), $"[Client-{client.LocalClientId}][Connected ({client.IsConnectedClient})] Still has client identifier {i}!"); - } - else - { - Assert.IsTrue(client.ConnectedClientsIds.Contains(i), $"[Client-{client.LocalClientId}][Connected ({client.IsConnectedClient})] Still has client identifier {i}!"); - } - } - } - if (m_UseHost) - { - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(0ul)); - } - - for (var i = 1ul; i < 3ul; ++i) - { - if (i == disconnectedClient) - { - Assert.IsFalse(m_ServerNetworkManager.ConnectedClientsIds.Contains(i)); - } - else - { - Assert.IsTrue(m_ServerNetworkManager.ConnectedClientsIds.Contains(i)); - } - } - - // If disconnected, the server and the client that disconnected will be notified - Assert.AreEqual(2, m_ClientDisconnectCount); - // Host receives peer disconnect, dedicated server does not - Assert.AreEqual(m_UseHost ? 3 : 2, m_PeerDisconnectCount); - } - } -} diff --git a/Tests/Runtime/PeerDisconnectCallbackTests.cs.meta b/Tests/Runtime/PeerDisconnectCallbackTests.cs.meta deleted file mode 100644 index 2e6247f..0000000 --- a/Tests/Runtime/PeerDisconnectCallbackTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 283ae7cc9a0641c8b49dacad79242287 -timeCreated: 1699978638 \ No newline at end of file diff --git a/Tests/Runtime/Physics.meta b/Tests/Runtime/Physics.meta deleted file mode 100644 index 18693af..0000000 --- a/Tests/Runtime/Physics.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 58745956b2a1e8346a48c5179cb247eb -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs b/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs deleted file mode 100644 index 089eeee..0000000 --- a/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS2D -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Components; -using UnityEngine; -using UnityEngine.TestTools; -using Unity.Netcode.TestHelpers.Runtime; - -namespace Unity.Netcode.RuntimeTests -{ - internal class NetworkRigidbody2DDynamicTest : NetworkRigidbody2DTestBase - { - public override bool Kinematic => false; - } - - internal class NetworkRigidbody2DKinematicTest : NetworkRigidbody2DTestBase - { - public override bool Kinematic => true; - } - - public abstract class NetworkRigidbody2DTestBase : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - public abstract bool Kinematic { get; } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.GetComponent().interpolation = RigidbodyInterpolation2D.Interpolate; - m_PlayerPrefab.GetComponent().isKinematic = Kinematic; - } - - /// - /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. - /// - /// - [UnityTest] - public IEnumerator TestRigidbodyKinematicEnableDisable() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ServerNetworkManager, serverClientPlayerResult); - var serverPlayer = serverClientPlayerResult.Result.gameObject; - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientClientPlayerResult = new NetcodeIntegrationTestHelpers.ResultWrapper(); - yield return NetcodeIntegrationTestHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId), m_ClientNetworkManagers[0], clientClientPlayerResult); - var clientPlayer = clientClientPlayerResult.Result.gameObject; - - Assert.IsNotNull(serverPlayer); - Assert.IsNotNull(clientPlayer); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // server rigidbody has authority and should have a kinematic mode of false - Assert.True(serverPlayer.GetComponent().isKinematic == Kinematic); - Assert.AreEqual(RigidbodyInterpolation2D.Interpolate, serverPlayer.GetComponent().interpolation); - - // client rigidbody has no authority and should have a kinematic mode of true - Assert.True(clientPlayer.GetComponent().isKinematic); - Assert.AreEqual(RigidbodyInterpolation2D.None, clientPlayer.GetComponent().interpolation); - - // despawn the server player, (but keep it around on the server) - serverPlayer.GetComponent().Despawn(false); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - // This should equal Kinematic - Assert.IsTrue(serverPlayer.GetComponent().isKinematic == Kinematic); - - yield return WaitForTicks(m_ServerNetworkManager, 5); - - Assert.IsTrue(clientPlayer == null); // safety check that object is actually despawned. - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS2D diff --git a/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta b/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta deleted file mode 100644 index 48faa51..0000000 --- a/Tests/Runtime/Physics/NetworkRigidbody2DTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f33b2f298cbb7b248b2a76ba48ee1d53 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Physics/NetworkRigidbodyTest.cs b/Tests/Runtime/Physics/NetworkRigidbodyTest.cs deleted file mode 100644 index 601a1ba..0000000 --- a/Tests/Runtime/Physics/NetworkRigidbodyTest.cs +++ /dev/null @@ -1,495 +0,0 @@ -#if COM_UNITY_MODULES_PHYSICS -using System.Collections; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(RigidbodyInterpolation.Interpolate, true, true)] // This should be allowed under all condistions when using Rigidbody motion - [TestFixture(RigidbodyInterpolation.Extrapolate, true, true)] // This should not allow extrapolation on non-auth instances when using Rigidbody motion & NT interpolation - [TestFixture(RigidbodyInterpolation.Extrapolate, false, true)] // This should allow extrapolation on non-auth instances when using Rigidbody & NT has no interpolation - [TestFixture(RigidbodyInterpolation.Interpolate, true, false)] // This should not allow kinematic instances to have Rigidbody interpolation enabled - [TestFixture(RigidbodyInterpolation.Interpolate, false, false)] // Testing that rigid body interpolation remains the same if NT interpolate is disabled - internal class NetworkRigidbodyTest : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - private bool m_NetworkTransformInterpolate; - private bool m_UseRigidBodyForMotion; - private RigidbodyInterpolation m_RigidbodyInterpolation; - - public NetworkRigidbodyTest(RigidbodyInterpolation rigidbodyInterpolation, bool networkTransformInterpolate, bool useRigidbodyForMotion) - { - m_RigidbodyInterpolation = rigidbodyInterpolation; - m_NetworkTransformInterpolate = networkTransformInterpolate; - m_UseRigidBodyForMotion = useRigidbodyForMotion; - } - - protected override void OnCreatePlayerPrefab() - { - var networkTransform = m_PlayerPrefab.AddComponent(); - networkTransform.Interpolate = m_NetworkTransformInterpolate; - var rigidbody = m_PlayerPrefab.AddComponent(); - rigidbody.interpolation = m_RigidbodyInterpolation; - var networkRigidbody = m_PlayerPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = m_UseRigidBodyForMotion; - } - - /// - /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly. - /// - /// - [UnityTest] - public IEnumerator TestRigidbodyKinematicEnableDisable() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerInstance = m_ServerNetworkManager.ConnectedClients[m_ClientNetworkManagers[0].LocalClientId].PlayerObject; - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientPlayerInstance = m_ClientNetworkManagers[0].LocalClient.PlayerObject; - - Assert.IsNotNull(serverClientPlayerInstance, $"{nameof(serverClientPlayerInstance)} is null!"); - Assert.IsNotNull(clientPlayerInstance, $"{nameof(clientPlayerInstance)} is null!"); - - var serverClientInstanceRigidBody = serverClientPlayerInstance.GetComponent(); - var clientRigidBody = clientPlayerInstance.GetComponent(); - - if (m_UseRigidBodyForMotion) - { - var interpolateCompareNonAuthoritative = m_NetworkTransformInterpolate ? RigidbodyInterpolation.Interpolate : m_RigidbodyInterpolation; - - // Server authoritative NT should yield non-kinematic mode for the server-side player instance - Assert.False(serverClientInstanceRigidBody.isKinematic, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is kinematic!"); - - // The authoritative instance can be None, Interpolate, or Extrapolate for the Rigidbody interpolation settings. - Assert.AreEqual(m_RigidbodyInterpolation, serverClientInstanceRigidBody.interpolation, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {serverClientInstanceRigidBody.interpolation} and not {m_RigidbodyInterpolation}!"); - - // Server authoritative NT should yield kinematic mode for the client-side player instance - Assert.True(clientRigidBody.isKinematic, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic!"); - - // When using Rigidbody motion, authoritative and non-authoritative Rigidbody interpolation settings should be preserved (except when extrapolation is used - Assert.AreEqual(interpolateCompareNonAuthoritative, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {interpolateCompareNonAuthoritative}!"); - } - else - { - // server rigidbody has authority and should not be kinematic - Assert.False(serverClientInstanceRigidBody.isKinematic, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is kinematic!"); - Assert.AreEqual(RigidbodyInterpolation.Interpolate, serverClientInstanceRigidBody.interpolation, $"[Server-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {serverClientInstanceRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.Interpolate)}!"); - - // Server authoritative NT should yield kinematic mode for the client-side player instance - Assert.True(clientRigidBody.isKinematic, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic!"); - - // client rigidbody has no authority with NT interpolation disabled should allow Rigidbody interpolation - if (!m_NetworkTransformInterpolate) - { - Assert.AreEqual(RigidbodyInterpolation.Interpolate, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.Interpolate)}!"); - } - else - { - Assert.AreEqual(RigidbodyInterpolation.None, clientRigidBody.interpolation, $"[Client-Side] Client-{m_ClientNetworkManagers[0].LocalClientId} " + - $"player's {nameof(Rigidbody)}'s interpolation is {clientRigidBody.interpolation} and not {nameof(RigidbodyInterpolation.None)}!"); - } - } - - // despawn the server player (but keep it around on the server) - serverClientPlayerInstance.Despawn(false); - - yield return WaitForConditionOrTimeOut(() => !serverClientPlayerInstance.IsSpawned && !clientPlayerInstance.IsSpawned); - AssertOnTimeout("Timed out waiting for client player to despawn on both server and client!"); - - // When despawned, we should always be kinematic (i.e. don't apply physics when despawned) - Assert.True(serverClientInstanceRigidBody.isKinematic, $"[Server-Side][Despawned] Client-{m_ClientNetworkManagers[0].LocalClientId} player's {nameof(Rigidbody)} is not kinematic when despawned!"); - Assert.IsTrue(clientPlayerInstance == null, $"[Client-Side] Player {nameof(NetworkObject)} is not null!"); - } - } - - internal class ContactEventTransformHelperWithInfo : ContactEventTransformHelper, IContactEventHandlerWithInfo - { - public ContactEventHandlerInfo GetContactEventHandlerInfo() - { - var contactEventHandlerInfo = new ContactEventHandlerInfo() - { - HasContactEventPriority = IsOwner, - ProvideNonRigidBodyContactEvents = m_EnableNonRigidbodyContacts.Value, - }; - return contactEventHandlerInfo; - } - - protected override void OnRegisterForContactEvents(bool isRegistering) - { - RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); - } - } - - - internal class ContactEventTransformHelper : NetworkTransform, IContactEventHandler - { - public static Vector3 SessionOwnerSpawnPoint; - public static Vector3 ClientSpawnPoint; - public static bool VerboseDebug; - public enum HelperStates - { - None, - MoveForward, - } - - private HelperStates m_HelperState; - - public void SetHelperState(HelperStates state) - { - m_HelperState = state; - if (!m_NetworkRigidbody.IsKinematic()) - { - m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; - m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; - } - m_NetworkRigidbody.Rigidbody.isKinematic = m_HelperState == HelperStates.None; - if (!m_NetworkRigidbody.IsKinematic()) - { - m_NetworkRigidbody.Rigidbody.angularVelocity = Vector3.zero; - m_NetworkRigidbody.Rigidbody.linearVelocity = Vector3.zero; - } - - } - - protected struct ContactEventInfo - { - public ulong EventId; - public Vector3 AveragedCollisionNormal; - public Rigidbody CollidingBody; - public Vector3 ContactPoint; - } - - protected List m_ContactEvents = new List(); - - protected NetworkVariable m_EnableNonRigidbodyContacts = new NetworkVariable(false, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); - - protected NetworkRigidbody m_NetworkRigidbody; - public ContactEventTransformHelper Target; - - public bool HasContactEvents() - { - return m_ContactEvents.Count > 0; - } - - public Rigidbody GetRigidbody() - { - return m_NetworkRigidbody.Rigidbody; - } - - public bool HadContactWith(ContactEventTransformHelper otherObject) - { - if (otherObject == null) - { - return false; - } - foreach (var contactEvent in m_ContactEvents) - { - if (contactEvent.CollidingBody == otherObject.m_NetworkRigidbody.Rigidbody) - { - return true; - } - } - return false; - } - - protected virtual void CheckToStopMoving() - { - SetHelperState(HadContactWith(Target) ? HelperStates.None : HelperStates.MoveForward); - } - - public void ContactEvent(ulong eventId, Vector3 averagedCollisionNormal, Rigidbody collidingBody, Vector3 contactPoint, bool hasCollisionStay = false, Vector3 averagedCollisionStayNormal = default) - { - if (Target == null) - { - return; - } - - if (collidingBody != null) - { - Log($">>>>>>> contact event with {collidingBody.name}!"); - } - else - { - Log($">>>>>>> contact event with non-rigidbody!"); - } - - m_ContactEvents.Add(new ContactEventInfo() - { - EventId = eventId, - AveragedCollisionNormal = averagedCollisionNormal, - CollidingBody = collidingBody, - ContactPoint = contactPoint, - }); - CheckToStopMoving(); - } - - private void SetInitialPositionClientServer() - { - if (IsServer) - { - if (!NetworkManager.DistributedAuthorityMode && !IsLocalPlayer) - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } - else - { - transform.position = SessionOwnerSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; - } - } - else - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } - } - - private void SetInitialPositionDistributedAuthority() - { - if (HasAuthority) - { - if (IsSessionOwner) - { - transform.position = SessionOwnerSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = SessionOwnerSpawnPoint; - } - else - { - transform.position = ClientSpawnPoint; - m_NetworkRigidbody.Rigidbody.position = ClientSpawnPoint; - } - } - } - - public override void OnNetworkSpawn() - { - m_NetworkRigidbody = GetComponent(); - - m_NetworkRigidbody.Rigidbody.maxLinearVelocity = 15; - m_NetworkRigidbody.Rigidbody.maxAngularVelocity = 10; - - if (NetworkManager.DistributedAuthorityMode) - { - SetInitialPositionDistributedAuthority(); - } - else - { - SetInitialPositionClientServer(); - } - if (IsLocalPlayer) - { - RegisterForContactEvents(true); - } - else - { - m_NetworkRigidbody.Rigidbody.detectCollisions = false; - } - base.OnNetworkSpawn(); - } - - protected virtual void OnRegisterForContactEvents(bool isRegistering) - { - RigidbodyContactEventManager.Instance.RegisterHandler(this, isRegistering); - } - - public void RegisterForContactEvents(bool isRegistering) - { - OnRegisterForContactEvents(isRegistering); - } - - private void FixedUpdate() - { - if (!IsSpawned || !IsOwner || m_HelperState != HelperStates.MoveForward) - { - return; - } - var distance = Vector3.Distance(Target.transform.position, transform.position); - var moveAmount = Mathf.Max(1.2f, distance); - // Head towards our target - var dir = (Target.transform.position - transform.position).normalized; - var deltaMove = dir * moveAmount * Time.fixedDeltaTime; - m_NetworkRigidbody.Rigidbody.MovePosition(m_NetworkRigidbody.Rigidbody.position + deltaMove); - - - Log($" Loc: {transform.position} | Dest: {Target.transform.position} | Dist: {distance} | MoveDelta: {deltaMove}"); - } - - protected void Log(string msg) - { - if (VerboseDebug) - { - Debug.Log($"Client-{OwnerClientId} {msg}"); - } - } - } - - [TestFixture(HostOrServer.Host, ContactEventTypes.Default)] - [TestFixture(HostOrServer.DAHost, ContactEventTypes.Default)] - [TestFixture(HostOrServer.Host, ContactEventTypes.WithInfo)] - [TestFixture(HostOrServer.DAHost, ContactEventTypes.WithInfo)] - internal class RigidbodyContactEventManagerTests : IntegrationTestWithApproximation - { - protected override int NumberOfClients => 1; - - - private GameObject m_RigidbodyContactEventManager; - - public enum ContactEventTypes - { - Default, - WithInfo - } - - private ContactEventTypes m_ContactEventType; - private StringBuilder m_ErrorLogger = new StringBuilder(); - - public RigidbodyContactEventManagerTests(HostOrServer hostOrServer, ContactEventTypes contactEventType) : base(hostOrServer) - { - m_ContactEventType = contactEventType; - } - - protected override void OnCreatePlayerPrefab() - { - ContactEventTransformHelper.SessionOwnerSpawnPoint = GetRandomVector3(-4, -3); - ContactEventTransformHelper.ClientSpawnPoint = GetRandomVector3(3, 4); - if (m_ContactEventType == ContactEventTypes.Default) - { - var helper = m_PlayerPrefab.AddComponent(); - helper.AuthorityMode = NetworkTransform.AuthorityModes.Owner; - } - else - { - var helperWithInfo = m_PlayerPrefab.AddComponent(); - helperWithInfo.AuthorityMode = NetworkTransform.AuthorityModes.Owner; - } - - var rigidbody = m_PlayerPrefab.AddComponent(); - rigidbody.useGravity = false; - rigidbody.isKinematic = true; - rigidbody.mass = 5.0f; - rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; - var sphereCollider = m_PlayerPrefab.AddComponent(); - sphereCollider.radius = 0.5f; - sphereCollider.providesContacts = true; - - var networkRigidbody = m_PlayerPrefab.AddComponent(); - networkRigidbody.UseRigidBodyForMotion = true; - networkRigidbody.AutoUpdateKinematicState = false; - - m_RigidbodyContactEventManager = new GameObject(); - m_RigidbodyContactEventManager.AddComponent(); - } - - - - private bool PlayersSpawnedInRightLocation() - { - var position = m_ServerNetworkManager.LocalClient.PlayerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{m_ServerNetworkManager.LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); - return false; - } - - position = m_ClientNetworkManagers[0].LocalClient.PlayerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{m_ClientNetworkManagers[0].LocalClientId} player position {position} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); - return false; - } - var playerObject = (NetworkObject)null; - if (!m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(m_ClientNetworkManagers[0].LocalClient.PlayerObject.NetworkObjectId)) - { - m_ErrorLogger.AppendLine($"Client-{m_ServerNetworkManager.LocalClientId} cannot find a local spawned instance of Client-{m_ClientNetworkManagers[0].LocalClientId}'s player object!"); - return false; - } - playerObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_ClientNetworkManagers[0].LocalClient.PlayerObject.NetworkObjectId]; - position = playerObject.transform.position; - - if (!Approximately(ContactEventTransformHelper.ClientSpawnPoint, position)) - { - m_ErrorLogger.AppendLine($"Client-{m_ServerNetworkManager.LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.ClientSpawnPoint}!"); - return false; - } - - if (!m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects.ContainsKey(m_ServerNetworkManager.LocalClient.PlayerObject.NetworkObjectId)) - { - m_ErrorLogger.AppendLine($"Client-{m_ClientNetworkManagers[0].LocalClientId} cannot find a local spawned instance of Client-{m_ServerNetworkManager.LocalClientId}'s player object!"); - return false; - } - playerObject = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[m_ServerNetworkManager.LocalClient.PlayerObject.NetworkObjectId]; - position = playerObject.transform.position; - if (!Approximately(ContactEventTransformHelper.SessionOwnerSpawnPoint, playerObject.transform.position)) - { - m_ErrorLogger.AppendLine($"Client-{m_ClientNetworkManagers[0].LocalClientId} player position {position} for Client-{playerObject.OwnerClientId} does not match the assigned player position {ContactEventTransformHelper.SessionOwnerSpawnPoint}!"); - return false; - } - return true; - } - - - [UnityTest] - public IEnumerator TestContactEvents() - { - ContactEventTransformHelper.VerboseDebug = m_EnableVerboseDebug; - - m_PlayerPrefab.SetActive(false); - m_ErrorLogger.Clear(); - // Validate all instances are spawned in the right location - yield return WaitForConditionOrTimeOut(PlayersSpawnedInRightLocation); - AssertOnTimeout($"Timed out waiting for all player instances to spawn in the corect location:\n {m_ErrorLogger}"); - m_ErrorLogger.Clear(); - - var sessionOwnerPlayer = m_ContactEventType == ContactEventTypes.Default ? m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent() : - m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent(); - var clientPlayer = m_ContactEventType == ContactEventTypes.Default ? m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent() : - m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent(); - - // Get both players to point towards each other - sessionOwnerPlayer.Target = clientPlayer; - clientPlayer.Target = sessionOwnerPlayer; - - sessionOwnerPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); - clientPlayer.SetHelperState(ContactEventTransformHelper.HelperStates.MoveForward); - - - yield return WaitForConditionOrTimeOut(() => sessionOwnerPlayer.HadContactWith(clientPlayer) || clientPlayer.HadContactWith(sessionOwnerPlayer)); - AssertOnTimeout("Timed out waiting for a player to collide with another player!"); - - clientPlayer.RegisterForContactEvents(false); - sessionOwnerPlayer.RegisterForContactEvents(false); - var otherPlayer = m_ContactEventType == ContactEventTypes.Default ? m_ServerNetworkManager.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent() : - m_ServerNetworkManager.SpawnManager.SpawnedObjects[clientPlayer.NetworkObjectId].GetComponent(); - otherPlayer.RegisterForContactEvents(false); - otherPlayer = m_ContactEventType == ContactEventTypes.Default ? m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent() : - m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[sessionOwnerPlayer.NetworkObjectId].GetComponent(); - otherPlayer.RegisterForContactEvents(false); - - Object.Destroy(m_RigidbodyContactEventManager); - m_RigidbodyContactEventManager = null; - } - - protected override IEnumerator OnTearDown() - { - // In case of a test failure - if (m_RigidbodyContactEventManager) - { - Object.Destroy(m_RigidbodyContactEventManager); - m_RigidbodyContactEventManager = null; - } - - return base.OnTearDown(); - } - } -} -#endif // COM_UNITY_MODULES_PHYSICS diff --git a/Tests/Runtime/Physics/NetworkRigidbodyTest.cs.meta b/Tests/Runtime/Physics/NetworkRigidbodyTest.cs.meta deleted file mode 100644 index 777618f..0000000 --- a/Tests/Runtime/Physics/NetworkRigidbodyTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 344ba3f81f24b6d40afb926333fd118d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/PlayerObjectTests.cs b/Tests/Runtime/PlayerObjectTests.cs deleted file mode 100644 index e382bcf..0000000 --- a/Tests/Runtime/PlayerObjectTests.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class PlayerObjectTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - protected GameObject m_NewPlayerToSpawn; - - public PlayerObjectTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override void OnServerAndClientsCreated() - { - m_NewPlayerToSpawn = CreateNetworkObjectPrefab("NewPlayerInstance"); - base.OnServerAndClientsCreated(); - } - - [UnityTest] - public IEnumerator SpawnAndReplaceExistingPlayerObject() - { - yield return WaitForConditionOrTimeOut(() => m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_ClientNetworkManagers[0].LocalClientId)); - AssertOnTimeout("Timed out waiting for client-side player object to spawn!"); - // Get the server-side player NetworkObject - var originalPlayer = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId]; - // Get the client-side player NetworkObject - var playerLocalClient = m_ClientNetworkManagers[0].LocalClient.PlayerObject; - - // Create a new player prefab instance - var newPlayer = Object.Instantiate(m_NewPlayerToSpawn); - var newPlayerNetworkObject = newPlayer.GetComponent(); - // In distributed authority mode, the client owner spawns its new player - newPlayerNetworkObject.NetworkManagerOwner = m_DistributedAuthority ? m_ClientNetworkManagers[0] : m_ServerNetworkManager; - // Spawn this instance as a new player object for the client who already has an assigned player object - newPlayerNetworkObject.SpawnAsPlayerObject(m_ClientNetworkManagers[0].LocalClientId); - - // Make sure server-side changes are detected, the original player object should no longer be marked as a player - // and the local new player object should. - yield return WaitForConditionOrTimeOut(() => !originalPlayer.IsPlayerObject && newPlayerNetworkObject.IsPlayerObject); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for server-side player object to change!"); - - // Make sure the client-side changes are the same - yield return WaitForConditionOrTimeOut(() => m_ClientNetworkManagers[0].LocalClient.PlayerObject != playerLocalClient && !playerLocalClient.IsPlayerObject - && m_ClientNetworkManagers[0].LocalClient.PlayerObject.IsPlayerObject); - Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for client-side player object to change!"); - } - } - - /// - /// Validate that when auto-player spawning but SpawnWithObservers is disabled, - /// the player instantiated is only spawned on the authority side. - /// - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class PlayerSpawnNoObserversTest : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - public PlayerSpawnNoObserversTest(HostOrServer hostOrServer) : base(hostOrServer) { } - - protected override bool ShouldCheckForSpawnedPlayers() - { - return false; - } - - protected override void OnCreatePlayerPrefab() - { - var playerNetworkObject = m_PlayerPrefab.GetComponent(); - playerNetworkObject.SpawnWithObservers = false; - base.OnCreatePlayerPrefab(); - } - - [UnityTest] - public IEnumerator SpawnWithNoObservers() - { - yield return s_DefaultWaitForTick; - - if (!m_DistributedAuthority) - { - // Make sure clients did not spawn their player object on any of the clients including the owner. - foreach (var client in m_ClientNetworkManagers) - { - foreach (var playerObject in m_ServerNetworkManager.SpawnManager.PlayerObjects) - { - Assert.IsFalse(client.SpawnManager.SpawnedObjects.ContainsKey(playerObject.NetworkObjectId), $"Client-{client.LocalClientId} spawned player object for Client-{playerObject.NetworkObjectId}!"); - } - } - } - else - { - // For distributed authority, we want to make sure the player object is only spawned on the authority side and all non-authority instances did not spawn it. - var playerObjectId = m_ServerNetworkManager.LocalClient.PlayerObject.NetworkObjectId; - foreach (var client in m_ClientNetworkManagers) - { - Assert.IsFalse(client.SpawnManager.SpawnedObjects.ContainsKey(playerObjectId), $"Client-{client.LocalClientId} spawned player object for Client-{m_ServerNetworkManager.LocalClientId}!"); - } - - foreach (var clientPlayer in m_ClientNetworkManagers) - { - playerObjectId = clientPlayer.LocalClient.PlayerObject.NetworkObjectId; - Assert.IsFalse(m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(playerObjectId), $"Client-{m_ServerNetworkManager.LocalClientId} spawned player object for Client-{clientPlayer.LocalClientId}!"); - foreach (var client in m_ClientNetworkManagers) - { - if (clientPlayer == client) - { - continue; - } - Assert.IsFalse(client.SpawnManager.SpawnedObjects.ContainsKey(playerObjectId), $"Client-{client.LocalClientId} spawned player object for Client-{clientPlayer.LocalClientId}!"); - } - } - - } - } - } - - /// - /// This test validates the player position and rotation is correct - /// relative to the prefab's initial settings if no changes are applied. - /// - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class PlayerSpawnPositionTests : IntegrationTestWithApproximation - { - protected override int NumberOfClients => 2; - - public PlayerSpawnPositionTests(HostOrServer hostOrServer) : base(hostOrServer) { } - - private Vector3 m_PlayerPosition; - private Quaternion m_PlayerRotation; - - protected override void OnCreatePlayerPrefab() - { - var playerNetworkObject = m_PlayerPrefab.GetComponent(); - m_PlayerPosition = GetRandomVector3(-10.0f, 10.0f); - m_PlayerRotation = Quaternion.Euler(GetRandomVector3(-180.0f, 180.0f)); - playerNetworkObject.transform.position = m_PlayerPosition; - playerNetworkObject.transform.rotation = m_PlayerRotation; - base.OnCreatePlayerPrefab(); - } - - private void PlayerTransformMatches(NetworkObject player) - { - var position = player.transform.position; - var rotation = player.transform.rotation; - Assert.True(Approximately(m_PlayerPosition, position), $"Client-{player.OwnerClientId} position {position} does not match the prefab position {m_PlayerPosition}!"); - Assert.True(Approximately(m_PlayerRotation, rotation), $"Client-{player.OwnerClientId} rotation {rotation.eulerAngles} does not match the prefab rotation {m_PlayerRotation.eulerAngles}!"); - } - - [UnityTest] - public IEnumerator PlayerSpawnPosition() - { - if (m_ServerNetworkManager.IsHost) - { - PlayerTransformMatches(m_ServerNetworkManager.LocalClient.PlayerObject); - - foreach (var client in m_ClientNetworkManagers) - { - yield return WaitForConditionOrTimeOut(() => client.SpawnManager.SpawnedObjects.ContainsKey(m_ServerNetworkManager.LocalClient.PlayerObject.NetworkObjectId)); - AssertOnTimeout($"Client-{client.LocalClientId} does not contain a player prefab instance for client-{m_ServerNetworkManager.LocalClientId}!"); - PlayerTransformMatches(client.SpawnManager.SpawnedObjects[m_ServerNetworkManager.LocalClient.PlayerObject.NetworkObjectId]); - } - } - - foreach (var client in m_ClientNetworkManagers) - { - yield return WaitForConditionOrTimeOut(() => m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(client.LocalClient.PlayerObject.NetworkObjectId)); - AssertOnTimeout($"Client-{m_ServerNetworkManager.LocalClientId} does not contain a player prefab instance for client-{client.LocalClientId}!"); - PlayerTransformMatches(m_ServerNetworkManager.SpawnManager.SpawnedObjects[client.LocalClient.PlayerObject.NetworkObjectId]); - foreach (var subClient in m_ClientNetworkManagers) - { - yield return WaitForConditionOrTimeOut(() => subClient.SpawnManager.SpawnedObjects.ContainsKey(client.LocalClient.PlayerObject.NetworkObjectId)); - AssertOnTimeout($"Client-{subClient.LocalClientId} does not contain a player prefab instance for client-{client.LocalClientId}!"); - PlayerTransformMatches(subClient.SpawnManager.SpawnedObjects[client.LocalClient.PlayerObject.NetworkObjectId]); - } - } - } - } -} diff --git a/Tests/Runtime/PlayerObjectTests.cs.meta b/Tests/Runtime/PlayerObjectTests.cs.meta deleted file mode 100644 index 1e25743..0000000 --- a/Tests/Runtime/PlayerObjectTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ee94262f06e591e45a9382582013cf7a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Profiling.meta b/Tests/Runtime/Profiling.meta deleted file mode 100644 index 617845c..0000000 --- a/Tests/Runtime/Profiling.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6b613c8dd4ba7d046b62971a3cb631ed -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Profiling/NetworkVariableNameTests.cs b/Tests/Runtime/Profiling/NetworkVariableNameTests.cs deleted file mode 100644 index 1ec8333..0000000 --- a/Tests/Runtime/Profiling/NetworkVariableNameTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; - -namespace Unity.Netcode.RuntimeTests -{ - internal sealed class NetworkVariableNameTests - { - private NetworkVariableNameComponent m_NetworkVariableNameComponent; - - [SetUp] - public void SetUp() - { - NetworkManagerHelper.StartNetworkManager(out _); - - var gameObjectId = NetworkManagerHelper.AddGameNetworkObject(Guid.NewGuid().ToString()); - m_NetworkVariableNameComponent = NetworkManagerHelper.AddComponentToObject(gameObjectId); - NetworkManagerHelper.SpawnNetworkObject(gameObjectId); - } - - [TearDown] - public void TearDown() - { - NetworkManagerHelper.ShutdownNetworkManager(); - } - - [Test] - public void VerifyNetworkVariableNameInitialization() - { - // Fields have regular naming - Assert.AreEqual(nameof(NetworkVariableNameComponent.NetworkVarList), m_NetworkVariableNameComponent.NetworkVarList.Name); - } - - private class NetworkVariableNameComponent : NetworkBehaviour - { - public NetworkList NetworkVarList = new NetworkList(); - } - } -} diff --git a/Tests/Runtime/Profiling/NetworkVariableNameTests.cs.meta b/Tests/Runtime/Profiling/NetworkVariableNameTests.cs.meta deleted file mode 100644 index 6ddaf9d..0000000 --- a/Tests/Runtime/Profiling/NetworkVariableNameTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e10a16550007020409234a1efb1fa383 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/RpcManyClientsTests.cs b/Tests/Runtime/RpcManyClientsTests.cs deleted file mode 100644 index 5af6daa..0000000 --- a/Tests/Runtime/RpcManyClientsTests.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class RpcManyClientsObject : NetworkBehaviour - { - public int Count = 0; - public List ReceivedFrom = new List(); - [ServerRpc(RequireOwnership = false)] - public void ResponseServerRpc(ServerRpcParams rpcParams = default) - { - ReceivedFrom.Add(rpcParams.Receive.SenderClientId); - Count++; - } - - [ClientRpc] - public void NoParamsClientRpc() - { - ResponseServerRpc(); - } - - [ClientRpc] - public void OneParamClientRpc(int value) - { - ResponseServerRpc(); - } - - [ClientRpc] - public void TwoParamsClientRpc(int value1, int value2) - { - ResponseServerRpc(); - } - - [ClientRpc] - public void WithParamsClientRpc(ClientRpcParams param) - { - ResponseServerRpc(); - } - } - - internal class RpcManyClientsTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 10; - - protected override bool m_EnableTimeTravel => true; - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - private GameObject m_PrefabToSpawn; - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = PreparePrefab(typeof(RpcManyClientsObject)); - } - - public GameObject PreparePrefab(Type type) - { - var prefabToSpawn = new GameObject(); - prefabToSpawn.AddComponent(type); - var networkObjectPrefab = prefabToSpawn.AddComponent(); - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObjectPrefab); - m_ServerNetworkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn }); - foreach (var clientNetworkManager in m_ClientNetworkManagers) - { - clientNetworkManager.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Prefab = prefabToSpawn }); - } - return prefabToSpawn; - } - - [Test] - public void RpcManyClientsTest() - { - var spawnedObject = UnityEngine.Object.Instantiate(m_PrefabToSpawn); - var netSpawnedObject = spawnedObject.GetComponent(); - netSpawnedObject.NetworkManagerOwner = m_ServerNetworkManager; - - netSpawnedObject.Spawn(); - - var messageHookList = new List(); - var serverMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager); - serverMessageHookEntry.AssignMessageType(); - messageHookList.Add(serverMessageHookEntry); - foreach (var client in m_ClientNetworkManagers) - { - var clientMessageHookEntry = new MessageHookEntry(client); - clientMessageHookEntry.AssignMessageType(); - messageHookList.Add(clientMessageHookEntry); - } - var rpcMessageHooks = new MessageHooksConditional(messageHookList); - - var rpcManyClientsObject = netSpawnedObject.GetComponent(); - - rpcManyClientsObject.Count = 0; - rpcManyClientsObject.NoParamsClientRpc(); // RPC with no params - - // Check that all ServerRpcMessages were sent - WaitForConditionOrTimeOutWithTimeTravel(rpcMessageHooks); - - // Now provide a small window of time to let the server receive and process all messages - var success = WaitForConditionOrTimeOutWithTimeTravel(() => TotalClients == rpcManyClientsObject.Count); - Assert.True(success, $"Timed out wait for {nameof(rpcManyClientsObject.NoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!"); - - rpcManyClientsObject.Count = 0; - rpcManyClientsObject.OneParamClientRpc(0); // RPC with one param - rpcMessageHooks.Reset(); - WaitForConditionOrTimeOutWithTimeTravel(rpcMessageHooks); - - // Now provide a small window of time to let the server receive and process all messages - success = WaitForConditionOrTimeOutWithTimeTravel(() => TotalClients == rpcManyClientsObject.Count); - Assert.True(success, $"Timed out wait for {nameof(rpcManyClientsObject.OneParamClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!"); - - var param = new ClientRpcParams(); - - rpcManyClientsObject.Count = 0; - rpcManyClientsObject.TwoParamsClientRpc(0, 0); // RPC with two params - - rpcMessageHooks.Reset(); - WaitForConditionOrTimeOutWithTimeTravel(rpcMessageHooks); - // Now provide a small window of time to let the server receive and process all messages - success = WaitForConditionOrTimeOutWithTimeTravel(() => TotalClients == rpcManyClientsObject.Count); - Assert.True(success, $"Timed out wait for {nameof(rpcManyClientsObject.TwoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of {TotalClients} was received!"); - - rpcManyClientsObject.ReceivedFrom.Clear(); - rpcManyClientsObject.Count = 0; - var target = new List { m_ClientNetworkManagers[1].LocalClientId, m_ClientNetworkManagers[2].LocalClientId }; - param.Send.TargetClientIds = target; - rpcManyClientsObject.WithParamsClientRpc(param); - - messageHookList.Clear(); - var targetedClientMessageHookEntry = new MessageHookEntry(m_ClientNetworkManagers[1]); - targetedClientMessageHookEntry.AssignMessageType(); - messageHookList.Add(targetedClientMessageHookEntry); - targetedClientMessageHookEntry = new MessageHookEntry(m_ClientNetworkManagers[2]); - targetedClientMessageHookEntry.AssignMessageType(); - messageHookList.Add(targetedClientMessageHookEntry); - rpcMessageHooks = new MessageHooksConditional(messageHookList); - - WaitForConditionOrTimeOutWithTimeTravel(rpcMessageHooks); - - // Now provide a small window of time to let the server receive and process all messages - success = WaitForConditionOrTimeOutWithTimeTravel(() => 2 == rpcManyClientsObject.Count); - Assert.True(success, $"Timed out wait for {nameof(rpcManyClientsObject.TwoParamsClientRpc)}! Only {rpcManyClientsObject.Count} of 2 was received!"); - - // either of the 2 selected clients can reply to the server first, due to network timing - var possibility1 = new List { m_ClientNetworkManagers[1].LocalClientId, m_ClientNetworkManagers[2].LocalClientId }; - var possibility2 = new List { m_ClientNetworkManagers[2].LocalClientId, m_ClientNetworkManagers[1].LocalClientId }; - Debug.Assert(Enumerable.SequenceEqual(rpcManyClientsObject.ReceivedFrom, possibility1) || Enumerable.SequenceEqual(rpcManyClientsObject.ReceivedFrom, possibility2)); - } - } -} diff --git a/Tests/Runtime/RpcManyClientsTests.cs.meta b/Tests/Runtime/RpcManyClientsTests.cs.meta deleted file mode 100644 index a5df53a..0000000 --- a/Tests/Runtime/RpcManyClientsTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1fc23d25ed71f46ecadbff65a20522c8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/RpcQueueTests.cs b/Tests/Runtime/RpcQueueTests.cs deleted file mode 100644 index 5d7775f..0000000 --- a/Tests/Runtime/RpcQueueTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// The RpcQueue unit tests validate: - /// - Maximum buffer size that can be sent (currently 1MB is the default maximum `MessageQueueHistoryFrame` size) - /// - That all RPCs invoke at the appropriate `NetworkUpdateStage` (Client and Server) - /// - A lower level `MessageQueueContainer` test that validates `MessageQueueFrameItems` after they have been put into the queue - /// - internal class RpcQueueTests - { - [SetUp] - public void Setup() - { - // Create, instantiate, and host - Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _)); - } - - /// - /// This tests the RPC Queue outbound and inbound buffer capabilities. - /// - /// IEnumerator - [UnityTest, Order(2)] - public IEnumerator BufferDataValidation() - { - Guid gameObjectId = NetworkManagerHelper.AddGameNetworkObject("GrowingBufferObject"); - - var growingRpcBufferSizeComponent = NetworkManagerHelper.AddComponentToObject(gameObjectId); - - NetworkManagerHelper.SpawnNetworkObject(gameObjectId); - - // Start Testing - growingRpcBufferSizeComponent.EnableTesting = true; - - var testsAreComplete = growingRpcBufferSizeComponent.IsTestComplete(); - - // Wait for the RPC pipeline test to complete or if we exceeded the maximum iterations bail - while (!testsAreComplete) - { - yield return new WaitForSeconds(0.003f); - - testsAreComplete = growingRpcBufferSizeComponent.IsTestComplete(); - } - - // Stop Testing - growingRpcBufferSizeComponent.EnableTesting = false; - - // Just disable this once we are done. - growingRpcBufferSizeComponent.gameObject.SetActive(false); - - Assert.IsTrue(testsAreComplete); - } - - [TearDown] - public void TearDown() - { - // Stop, shutdown, and destroy - NetworkManagerHelper.ShutdownNetworkManager(); - } - } -} diff --git a/Tests/Runtime/RpcQueueTests.cs.meta b/Tests/Runtime/RpcQueueTests.cs.meta deleted file mode 100644 index 4309f8f..0000000 --- a/Tests/Runtime/RpcQueueTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9a96d73d8acaa2a4aadc4e6be8b10c7b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/RpcTests.cs b/Tests/Runtime/RpcTests.cs deleted file mode 100644 index 23c546e..0000000 --- a/Tests/Runtime/RpcTests.cs +++ /dev/null @@ -1,228 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; -using Vector3 = UnityEngine.Vector3; - -namespace Unity.Netcode.RuntimeTests -{ - internal class RpcTests : NetcodeIntegrationTest - { - internal class CompileTimeNoRpcsBaseClassTest : NetworkBehaviour - { - - } - - internal class CompileTimeHasRpcsChildClassDerivedFromNoRpcsBaseClassTest : CompileTimeNoRpcsBaseClassTest - { - [ServerRpc] - public void SomeDummyServerRpc() - { - - } - } - - internal class GenericRpcTestNB : NetworkBehaviour where T : unmanaged - { - public event Action OnServer_Rpc; - - [ServerRpc] - public void MyServerRpc(T clientId, ServerRpcParams param = default) - { - OnServer_Rpc(clientId, param); - } - } - - internal class RpcTestNBFloat : GenericRpcTestNB - { - } - - internal class RpcTestNB : GenericRpcTestNB - { -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public event Action, ServerRpcParams> OnNativeListServer_Rpc; -#endif - public event Action, -#endif - FixedString32Bytes> OnTypedServer_Rpc; - - public event Action OnClient_Rpc; - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ServerRpc] - public void MyNativeListServerRpc(NativeList clientId, ServerRpcParams param = default) - { - OnNativeListServer_Rpc(clientId, param); - } -#endif - - [ClientRpc] - public void MyClientRpc() - { - OnClient_Rpc(); - } - - [ServerRpc] - public void MyTypedServerRpc(Vector3 param1, Vector3[] param2, -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - NativeList param3, -#endif - FixedString32Bytes param4) - { - OnTypedServer_Rpc(param1, param2, -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - param3, -#endif - param4); - } - } - - protected override int NumberOfClients => 1; - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - m_PlayerPrefab.AddComponent(); - } - - [UnityTest] - public IEnumerator TestRpcs() - { - // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component - var serverClientRpcTestNB = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - var serverClientRpcTestNBFloat = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component - var localClienRpcTestNB = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - var localClienRpcTestNBFloat = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // Setup state - bool hasReceivedServerRpc = false; - bool hasReceivedFloatServerRpc = false; - bool hasReceivedTypedServerRpc = false; - bool hasReceivedClientRpcRemotely = false; - bool hasReceivedClientRpcLocally = false; - - var vector3 = new Vector3(1, 2, 3); - Vector3[] vector3s = new[] { new Vector3(4, 5, 6), new Vector3(7, 8, 9) }; -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - using var vector3sNativeList = new NativeList(Allocator.Persistent) - { - new Vector3(10, 11, 12), - new Vector3(13, 14, 15) - }; -#endif - - localClienRpcTestNB.OnClient_Rpc += () => - { - VerboseDebug("ClientRpc received on client object"); - hasReceivedClientRpcRemotely = true; - }; - - localClienRpcTestNB.OnServer_Rpc += (clientId, param) => - { - // The RPC invoked locally. (Weaver failure?) - Assert.Fail("ServerRpc invoked locally. Weaver failure?"); - }; - - localClienRpcTestNBFloat.OnServer_Rpc += (clientId, param) => - { - // The RPC invoked locally. (Weaver failure?) - Assert.Fail("ServerRpc (float) invoked locally. Weaver failure?"); - }; - - serverClientRpcTestNB.OnServer_Rpc += (clientId, param) => - { - VerboseDebug("ServerRpc received on server object"); - Assert.True(param.Receive.SenderClientId == clientId); - hasReceivedServerRpc = true; - }; - - serverClientRpcTestNBFloat.OnServer_Rpc += (clientId, param) => - { - VerboseDebug("ServerRpc (float) received on server object"); - Assert.True(param.Receive.SenderClientId == clientId); - hasReceivedFloatServerRpc = true; - }; - - serverClientRpcTestNB.OnClient_Rpc += () => - { - // The RPC invoked locally. (Weaver failure?) - VerboseDebug("ClientRpc received on server object"); - hasReceivedClientRpcLocally = true; - }; - - var str = new FixedString32Bytes("abcdefg"); - - serverClientRpcTestNB.OnTypedServer_Rpc += (param1, param2, - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - param3, -#endif - param4) => - { - VerboseDebug("TypedServerRpc received on server object"); - Assert.AreEqual(param1, vector3); - Assert.AreEqual(param2.Length, vector3s.Length); - Assert.AreEqual(param2[0], vector3s[0]); - Assert.AreEqual(param2[1], vector3s[1]); -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - Assert.AreEqual(param3.Length, vector3s.Length); - Assert.AreEqual(param3[0], vector3sNativeList[0]); - Assert.AreEqual(param3[1], vector3sNativeList[1]); -#endif - Assert.AreEqual(param4, str); - hasReceivedTypedServerRpc = true; - }; - - // Send ServerRpc - localClienRpcTestNB.MyServerRpc(m_ClientNetworkManagers[0].LocalClientId); - localClienRpcTestNBFloat.MyServerRpc(m_ClientNetworkManagers[0].LocalClientId); - - // Send TypedServerRpc - localClienRpcTestNB.MyTypedServerRpc(vector3, vector3s, -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - vector3sNativeList, -#endif - str); - - // Send ClientRpc - serverClientRpcTestNB.MyClientRpc(); - - // Validate each NetworkManager relative NetworkMessageManager received each respective RPC - var messageHookList = new List(); - var serverMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager); - serverMessageHookEntry.AssignMessageType(); - messageHookList.Add(serverMessageHookEntry); - - var typedServerMessageHookEntry = new MessageHookEntry(m_ServerNetworkManager); - typedServerMessageHookEntry.AssignMessageType(); - messageHookList.Add(typedServerMessageHookEntry); - - foreach (var client in m_ClientNetworkManagers) - { - var clientMessageHookEntry = new MessageHookEntry(client); - clientMessageHookEntry.AssignMessageType(); - messageHookList.Add(clientMessageHookEntry); - } - - var rpcMessageHooks = new MessageHooksConditional(messageHookList); - yield return WaitForConditionOrTimeOut(rpcMessageHooks); - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for messages: {rpcMessageHooks.GetHooksStillWaiting()}"); - - // Make sure RPCs propagated all the way up and were called on the relative destination class instance - yield return WaitForConditionOrTimeOut(() => hasReceivedServerRpc && hasReceivedClientRpcLocally && hasReceivedClientRpcRemotely && hasReceivedTypedServerRpc); - - Assert.True(hasReceivedServerRpc, "ServerRpc was not received"); - Assert.True(hasReceivedFloatServerRpc, "ServerRpc was not received"); - Assert.True(hasReceivedTypedServerRpc, "TypedServerRpc was not received"); - Assert.True(hasReceivedClientRpcLocally, "ClientRpc was not locally received on the server"); - Assert.True(hasReceivedClientRpcRemotely, "ClientRpc was not remotely received on the client"); - } - } -} diff --git a/Tests/Runtime/RpcTests.cs.meta b/Tests/Runtime/RpcTests.cs.meta deleted file mode 100644 index 02e7960..0000000 --- a/Tests/Runtime/RpcTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 46681ff78c6154f87acf5e1cccbfc0e1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/RpcTypeSerializationTests.cs b/Tests/Runtime/RpcTypeSerializationTests.cs deleted file mode 100644 index 8da15cc..0000000 --- a/Tests/Runtime/RpcTypeSerializationTests.cs +++ /dev/null @@ -1,1987 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Quaternion = UnityEngine.Quaternion; -using Vector2 = UnityEngine.Vector2; -using Vector3 = UnityEngine.Vector3; -using Vector4 = UnityEngine.Vector4; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class RpcTypeSerializationTests : NetcodeIntegrationTest - { - public RpcTypeSerializationTests() - { - m_UseHost = false; - } - - internal class RpcTestNB : NetworkBehaviour - { - public delegate void OnReceivedDelegate(object obj); - public OnReceivedDelegate OnReceived; - - [ClientRpc] - public void ByteClientRpc(byte value) - { - OnReceived(value); - } - - [ClientRpc] - public void ByteArrayClientRpc(byte[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ByteNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ByteNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void SbyteClientRpc(sbyte value) - { - OnReceived(value); - } - - [ClientRpc] - public void SbyteArrayClientRpc(sbyte[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void SbyteNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void SbyteNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void ShortClientRpc(short value) - { - OnReceived(value); - } - - [ClientRpc] - public void ShortArrayClientRpc(short[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ShortNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ShortNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void UshortClientRpc(ushort value) - { - OnReceived(value); - } - - [ClientRpc] - public void UshortArrayClientRpc(ushort[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void UshortNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void UshortNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void IntClientRpc(int value) - { - OnReceived(value); - } - - [ClientRpc] - public void IntArrayClientRpc(int[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void IntNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void IntNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void UintClientRpc(uint value) - { - OnReceived(value); - } - - [ClientRpc] - public void UintArrayClientRpc(uint[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void UintNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void UintNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void LongClientRpc(long value) - { - OnReceived(value); - } - - [ClientRpc] - public void LongArrayClientRpc(long[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void LongNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void LongNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void UlongClientRpc(ulong value) - { - OnReceived(value); - } - - [ClientRpc] - public void UlongArrayClientRpc(ulong[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void UlongNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void UlongNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void BoolClientRpc(bool value) - { - OnReceived(value); - } - - [ClientRpc] - public void BoolArrayClientRpc(bool[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void BoolNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void BoolNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void CharClientRpc(char value) - { - OnReceived(value); - } - - [ClientRpc] - public void CharArrayClientRpc(char[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void CharNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void CharNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void FloatClientRpc(float value) - { - OnReceived(value); - } - - [ClientRpc] - public void FloatArrayClientRpc(float[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void FloatNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void FloatNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void DoubleClientRpc(double value) - { - OnReceived(value); - } - - [ClientRpc] - public void DoubleArrayClientRpc(double[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void DoubleNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void DoubleNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void ByteEnumClientRpc(ByteEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void ByteEnumArrayClientRpc(ByteEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ByteEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ByteEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void SByteEnumClientRpc(SByteEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void SByteEnumArrayClientRpc(SByteEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void SByteEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void SByteEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void ShortEnumClientRpc(ShortEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void ShortEnumArrayClientRpc(ShortEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ShortEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ShortEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void UShortEnumClientRpc(UShortEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void UShortEnumArrayClientRpc(UShortEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void UShortEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void UShortEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void IntEnumClientRpc(IntEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void IntEnumArrayClientRpc(IntEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void IntEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void IntEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void UIntEnumClientRpc(UIntEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void UIntEnumArrayClientRpc(UIntEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void UIntEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void UIntEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void LongEnumClientRpc(LongEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void LongEnumArrayClientRpc(LongEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void LongEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void LongEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void ULongEnumClientRpc(ULongEnum value) - { - OnReceived(value); - } - - [ClientRpc] - public void ULongEnumArrayClientRpc(ULongEnum[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ULongEnumNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ULongEnumNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Vector2ClientRpc(Vector2 value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector2ArrayClientRpc(Vector2[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector2NativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Vector2NativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Vector3ClientRpc(Vector3 value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector3ArrayClientRpc(Vector3[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector3NativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Vector3NativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Vector2IntClientRpc(Vector2Int value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector2IntArrayClientRpc(Vector2Int[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector2IntNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Vector2IntNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Vector3IntClientRpc(Vector3Int value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector3IntArrayClientRpc(Vector3Int[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector3IntNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Vector3IntNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Vector4ClientRpc(Vector4 value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector4ArrayClientRpc(Vector4[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Vector4NativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Vector4NativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void QuaternionClientRpc(Quaternion value) - { - OnReceived(value); - } - - [ClientRpc] - public void QuaternionArrayClientRpc(Quaternion[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void QuaternionNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void QuaternionNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void ColorClientRpc(Color value) - { - OnReceived(value); - } - - [ClientRpc] - public void ColorArrayClientRpc(Color[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void ColorNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void ColorNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Color32ClientRpc(Color32 value) - { - OnReceived(value); - } - - [ClientRpc] - public void Color32ArrayClientRpc(Color32[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Color32NativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Color32NativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void RayClientRpc(Ray value) - { - OnReceived(value); - } - - [ClientRpc] - public void RayArrayClientRpc(Ray[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void RayNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void RayNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void Ray2DClientRpc(Ray2D value) - { - OnReceived(value); - } - - [ClientRpc] - public void Ray2DArrayClientRpc(Ray2D[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void Ray2DNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void Ray2DNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void NetworkVariableTestStructClientRpc(NetworkVariableTestStruct value) - { - OnReceived(value); - } - - [ClientRpc] - public void NetworkVariableTestStructArrayClientRpc(NetworkVariableTestStruct[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void NetworkVariableTestStructNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void NetworkVariableTestStructNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - - [ClientRpc] - public void FixedString32BytesClientRpc(FixedString32Bytes value) - { - OnReceived(value); - } - - [ClientRpc] - public void FixedString32BytesArrayClientRpc(FixedString32Bytes[] value) - { - OnReceived(value); - } - - [ClientRpc] - public void FixedString32BytesNativeArrayClientRpc(NativeArray value) - { - OnReceived(value); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [ClientRpc] - public void FixedString32BytesNativeListClientRpc(NativeList value) - { - OnReceived(value); - } -#endif - } - - protected override int NumberOfClients => 1; - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - public IEnumerator TestValueType(T firstTest, T secondTest) where T : unmanaged - { - var methods = typeof(RpcTestNB).GetMethods(); - foreach (var method in methods) - { - var parms = method.GetParameters(); - if (parms.Length != 1) - { - continue; - } - if (parms[0].ParameterType == typeof(T) && method.Name.EndsWith("ClientRpc")) - { - object receivedValue = null; - - // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component - var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component - var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - clientObject.OnReceived = o => - { - receivedValue = o; - VerboseDebug($"Received value {o}"); - }; - VerboseDebug($"Sending first RPC with {firstTest}"); - method.Invoke(serverObject, new object[] { firstTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsNotNull(receivedValue); - - Assert.AreEqual(receivedValue.GetType(), typeof(T)); - var value = (T)receivedValue; - Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref value, ref firstTest)); - - receivedValue = null; - - VerboseDebug($"Sending second RPC with {secondTest}"); - method.Invoke(serverObject, new object[] { secondTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsNotNull(receivedValue); - - Assert.AreEqual(receivedValue.GetType(), typeof(T)); - value = (T)receivedValue; - Assert.IsTrue(NetworkVariableSerialization.AreEqual(ref value, ref secondTest)); - yield break; - } - } - Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); - } - - public IEnumerator TestValueTypeArray(T[] firstTest, T[] secondTest) where T : unmanaged - { - var methods = typeof(RpcTestNB).GetMethods(); - foreach (var method in methods) - { - var parms = method.GetParameters(); - if (parms.Length != 1) - { - continue; - } - if (parms[0].ParameterType == typeof(T[]) && method.Name.EndsWith("ClientRpc")) - { - object receivedValue = null; - - // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component - var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component - var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - clientObject.OnReceived = o => - { - receivedValue = o; - VerboseDebug($"Received value {o}"); - }; - VerboseDebug($"Sending first RPC with {firstTest}"); - method.Invoke(serverObject, new object[] { firstTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsNotNull(receivedValue); - - Assert.AreEqual(receivedValue.GetType(), typeof(T[])); - var value = (T[])receivedValue; - Assert.AreEqual(value, firstTest); - - receivedValue = null; - - VerboseDebug($"Sending second RPC with {secondTest}"); - method.Invoke(serverObject, new object[] { secondTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsNotNull(receivedValue); - - Assert.AreEqual(receivedValue.GetType(), typeof(T[])); - value = (T[])receivedValue; - Assert.AreEqual(value, secondTest); - - method.Invoke(serverObject, new object[] { null }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsNull(receivedValue); - yield break; - } - } - Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); - } - - public IEnumerator TestValueTypeNativeArray(NativeArray firstTest, NativeArray secondTest) where T : unmanaged - { - var methods = typeof(RpcTestNB).GetMethods(); - foreach (var method in methods) - { - var parms = method.GetParameters(); - if (parms.Length != 1) - { - continue; - } - if (parms[0].ParameterType == typeof(NativeArray) && method.Name.EndsWith("ClientRpc")) - { - var receivedValue = new NativeArray(); - - // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component - var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component - var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - clientObject.OnReceived = o => - { - Assert.AreEqual(o.GetType(), typeof(NativeArray)); - var oAsArray = (NativeArray)o; - receivedValue = new NativeArray(oAsArray, Allocator.Persistent); - VerboseDebug($"Received value {o}"); - }; - VerboseDebug($"Sending first RPC with {firstTest}"); - method.Invoke(serverObject, new object[] { firstTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsTrue(receivedValue.IsCreated); - - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref firstTest)); - receivedValue.Dispose(); - firstTest.Dispose(); - - receivedValue = new NativeArray(); - - VerboseDebug($"Sending second RPC with {secondTest}"); - method.Invoke(serverObject, new object[] { secondTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsTrue(receivedValue.IsCreated); - - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref secondTest)); - receivedValue.Dispose(); - secondTest.Dispose(); - yield break; - } - } - Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - public IEnumerator TestValueTypeNativeList(NativeList firstTest, NativeList secondTest) where T : unmanaged - { - var methods = typeof(RpcTestNB).GetMethods(); - foreach (var method in methods) - { - var parms = method.GetParameters(); - if (parms.Length != 1) - { - continue; - } - if (parms[0].ParameterType == typeof(NativeList) && method.Name.EndsWith("ClientRpc")) - { - var receivedValue = new NativeList(); - - // This is the *SERVER VERSION* of the *CLIENT PLAYER* RpcTestNB component - var serverObject = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* RpcTestNB component - var clientObject = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent(); - - clientObject.OnReceived = o => - { - Assert.AreEqual(o.GetType(), typeof(NativeList)); - var oAsList = (NativeList)o; - receivedValue = new NativeList(oAsList.Length, Allocator.Persistent); - foreach (var item in oAsList) - { - receivedValue.Add(item); - } - VerboseDebug($"Received value {o}"); - }; - VerboseDebug($"Sending first RPC with {firstTest}"); - method.Invoke(serverObject, new object[] { firstTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsTrue(receivedValue.IsCreated); - - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref firstTest)); - receivedValue.Dispose(); - firstTest.Dispose(); - - receivedValue = new NativeList(); - - VerboseDebug($"Sending second RPC with {secondTest}"); - method.Invoke(serverObject, new object[] { secondTest }); - - yield return WaitForMessageReceived(m_ClientNetworkManagers.ToList()); - - Assert.IsTrue(receivedValue.IsCreated); - - Assert.IsTrue(NetworkVariableSerialization>.AreEqual(ref receivedValue, ref secondTest)); - receivedValue.Dispose(); - secondTest.Dispose(); - yield break; - } - } - Assert.Fail($"Could not find RPC function for {typeof(T).Name}"); - } -#endif - - [UnityTest] - public IEnumerator WhenSendingAValueTypeOverAnRpc_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - yield return TestValueType(byte.MinValue + 5, byte.MaxValue); - } - else if (testType == typeof(sbyte)) - { - yield return TestValueType(sbyte.MinValue + 5, sbyte.MaxValue); - } - else if (testType == typeof(short)) - { - yield return TestValueType(short.MinValue + 5, short.MaxValue); - } - else if (testType == typeof(ushort)) - { - yield return TestValueType(ushort.MinValue + 5, ushort.MaxValue); - } - else if (testType == typeof(int)) - { - yield return TestValueType(int.MinValue + 5, int.MaxValue); - } - else if (testType == typeof(uint)) - { - yield return TestValueType(uint.MinValue + 5, uint.MaxValue); - } - else if (testType == typeof(long)) - { - yield return TestValueType(long.MinValue + 5, long.MaxValue); - } - else if (testType == typeof(ulong)) - { - yield return TestValueType(ulong.MinValue + 5, ulong.MaxValue); - } - else if (testType == typeof(bool)) - { - yield return TestValueType(true, false); - } - else if (testType == typeof(char)) - { - yield return TestValueType('z', ' '); - } - else if (testType == typeof(float)) - { - yield return TestValueType(float.MinValue + 5.12345678f, float.MaxValue); - } - else if (testType == typeof(double)) - { - yield return TestValueType(double.MinValue + 5.12345678, double.MaxValue); - } - else if (testType == typeof(ByteEnum)) - { - yield return TestValueType(ByteEnum.B, ByteEnum.C); - } - else if (testType == typeof(SByteEnum)) - { - yield return TestValueType(SByteEnum.B, SByteEnum.C); - } - else if (testType == typeof(ShortEnum)) - { - yield return TestValueType(ShortEnum.B, ShortEnum.C); - } - else if (testType == typeof(UShortEnum)) - { - yield return TestValueType(UShortEnum.B, UShortEnum.C); - } - else if (testType == typeof(IntEnum)) - { - yield return TestValueType(IntEnum.B, IntEnum.C); - } - else if (testType == typeof(UIntEnum)) - { - yield return TestValueType(UIntEnum.B, UIntEnum.C); - } - else if (testType == typeof(LongEnum)) - { - yield return TestValueType(LongEnum.B, LongEnum.C); - } - else if (testType == typeof(ULongEnum)) - { - yield return TestValueType(ULongEnum.B, ULongEnum.C); - } - else if (testType == typeof(Vector2)) - { - yield return TestValueType( - new Vector2(5, 10), - new Vector2(15, 20)); - } - else if (testType == typeof(Vector3)) - { - yield return TestValueType( - new Vector3(5, 10, 15), - new Vector3(20, 25, 30)); - } - else if (testType == typeof(Vector2Int)) - { - yield return TestValueType( - new Vector2Int(5, 10), - new Vector2Int(15, 20)); - } - else if (testType == typeof(Vector3Int)) - { - yield return TestValueType( - new Vector3Int(5, 10, 15), - new Vector3Int(20, 25, 30)); - } - else if (testType == typeof(Vector4)) - { - yield return TestValueType( - new Vector4(5, 10, 15, 20), - new Vector4(25, 30, 35, 40)); - } - else if (testType == typeof(Quaternion)) - { - yield return TestValueType( - new Quaternion(5, 10, 15, 20), - new Quaternion(25, 30, 35, 40)); - } - else if (testType == typeof(Color)) - { - yield return TestValueType( - new Color(1, 0, 0), - new Color(0, 1, 1)); - } - else if (testType == typeof(Color32)) - { - yield return TestValueType( - new Color32(255, 0, 0, 128), - new Color32(0, 255, 255, 255)); - } - else if (testType == typeof(Ray)) - { - yield return TestValueType( - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11))); - } - else if (testType == typeof(Ray2D)) - { - yield return TestValueType( - new Ray2D(new Vector2(0, 1), new Vector2(2, 3)), - new Ray2D(new Vector2(4, 5), new Vector2(6, 7))); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - yield return TestValueType(NetworkVariableTestStruct.GetTestStruct(), NetworkVariableTestStruct.GetTestStruct()); - } - else if (testType == typeof(FixedString32Bytes)) - { - yield return TestValueType(new FixedString32Bytes("foobar"), new FixedString32Bytes("12345678901234567890123456789")); - } - } - - [UnityTest] - public IEnumerator WhenSendingAnArrayOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - yield return TestValueTypeArray( - new byte[] { byte.MinValue + 5, byte.MaxValue }, - new byte[] { 0, byte.MinValue + 10, byte.MaxValue - 10 }); - } - else if (testType == typeof(sbyte)) - { - yield return TestValueTypeArray( - new sbyte[] { sbyte.MinValue + 5, sbyte.MaxValue }, - new sbyte[] { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }); - } - else if (testType == typeof(short)) - { - yield return TestValueTypeArray( - new short[] { short.MinValue + 5, short.MaxValue }, - new short[] { 0, short.MinValue + 10, short.MaxValue - 10 }); - } - else if (testType == typeof(ushort)) - { - yield return TestValueTypeArray( - new ushort[] { ushort.MinValue + 5, ushort.MaxValue }, - new ushort[] { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }); - } - else if (testType == typeof(int)) - { - yield return TestValueTypeArray( - new int[] { int.MinValue + 5, int.MaxValue }, - new int[] { 0, int.MinValue + 10, int.MaxValue - 10 }); - } - else if (testType == typeof(uint)) - { - yield return TestValueTypeArray( - new uint[] { uint.MinValue + 5, uint.MaxValue }, - new uint[] { 0, uint.MinValue + 10, uint.MaxValue - 10 }); - } - else if (testType == typeof(long)) - { - yield return TestValueTypeArray( - new long[] { long.MinValue + 5, long.MaxValue }, - new long[] { 0, long.MinValue + 10, long.MaxValue - 10 }); - } - else if (testType == typeof(ulong)) - { - yield return TestValueTypeArray( - new ulong[] { ulong.MinValue + 5, ulong.MaxValue }, - new ulong[] { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }); - } - else if (testType == typeof(bool)) - { - yield return TestValueTypeArray( - new bool[] { true, false, true }, - new bool[] { false, true, false, true, false }); - } - else if (testType == typeof(char)) - { - yield return TestValueTypeArray( - new char[] { 'z', ' ', '?' }, - new char[] { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }); - } - else if (testType == typeof(float)) - { - yield return TestValueTypeArray( - new float[] { float.MinValue + 5.12345678f, float.MaxValue }, - new float[] { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }); - } - else if (testType == typeof(double)) - { - yield return TestValueTypeArray( - new double[] { double.MinValue + 5.12345678, double.MaxValue }, - new double[] { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }); - } - else if (testType == typeof(ByteEnum)) - { - yield return TestValueTypeArray( - new ByteEnum[] { ByteEnum.C, ByteEnum.B, ByteEnum.A }, - new ByteEnum[] { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }); - } - else if (testType == typeof(SByteEnum)) - { - yield return TestValueTypeArray( - new SByteEnum[] { SByteEnum.C, SByteEnum.B, SByteEnum.A }, - new SByteEnum[] { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }); - } - else if (testType == typeof(ShortEnum)) - { - yield return TestValueTypeArray( - new ShortEnum[] { ShortEnum.C, ShortEnum.B, ShortEnum.A }, - new ShortEnum[] { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }); - } - else if (testType == typeof(UShortEnum)) - { - yield return TestValueTypeArray( - new UShortEnum[] { UShortEnum.C, UShortEnum.B, UShortEnum.A }, - new UShortEnum[] { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }); - } - else if (testType == typeof(IntEnum)) - { - yield return TestValueTypeArray( - new IntEnum[] { IntEnum.C, IntEnum.B, IntEnum.A }, - new IntEnum[] { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }); - } - else if (testType == typeof(UIntEnum)) - { - yield return TestValueTypeArray( - new UIntEnum[] { UIntEnum.C, UIntEnum.B, UIntEnum.A }, - new UIntEnum[] { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }); - } - else if (testType == typeof(LongEnum)) - { - yield return TestValueTypeArray( - new LongEnum[] { LongEnum.C, LongEnum.B, LongEnum.A }, - new LongEnum[] { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }); - } - else if (testType == typeof(ULongEnum)) - { - yield return TestValueTypeArray( - new ULongEnum[] { ULongEnum.C, ULongEnum.B, ULongEnum.A }, - new ULongEnum[] { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }); - } - else if (testType == typeof(Vector2)) - { - yield return TestValueTypeArray( - new Vector2[] { new Vector2(5, 10), new Vector2(15, 20) }, - new Vector2[] { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }); - } - else if (testType == typeof(Vector3)) - { - yield return TestValueTypeArray( - new Vector3[] { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, - new Vector3[] { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }); - } - else if (testType == typeof(Vector2Int)) - { - yield return TestValueTypeArray( - new Vector2Int[] { new Vector2Int(5, 10), new Vector2Int(15, 20) }, - new Vector2Int[] { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }); - } - else if (testType == typeof(Vector3Int)) - { - yield return TestValueTypeArray( - new Vector3Int[] { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, - new Vector3Int[] { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }); - } - else if (testType == typeof(Vector4)) - { - yield return TestValueTypeArray( - new Vector4[] { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, - new Vector4[] { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }); - } - else if (testType == typeof(Quaternion)) - { - yield return TestValueTypeArray( - new Quaternion[] { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, - new Quaternion[] { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }); - } - else if (testType == typeof(Color)) - { - yield return TestValueTypeArray( - new Color[] { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, - new Color[] { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }); - } - else if (testType == typeof(Color32)) - { - yield return TestValueTypeArray( - new Color32[] { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, - new Color32[] { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }); - } - else if (testType == typeof(Ray)) - { - yield return TestValueTypeArray( - new Ray[] - { - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), - }, - new Ray[] - { - new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), - new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), - new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), - }); - } - else if (testType == typeof(Ray2D)) - { - yield return TestValueTypeArray( - new Ray2D[] - { - new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), - new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), - }, - new Ray2D[] - { - new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), - new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), - new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), - }); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - yield return TestValueTypeArray( - new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, - new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }); - } - else if (testType == typeof(FixedString32Bytes)) - { - yield return TestValueTypeArray( - new FixedString32Bytes[] - { - new FixedString32Bytes("foobar"), - new FixedString32Bytes("12345678901234567890123456789") - }, - new FixedString32Bytes[] - { - new FixedString32Bytes("BazQux"), - new FixedString32Bytes("98765432109876543210987654321"), - new FixedString32Bytes("FixedString32Bytes") - }); - } - } - - [UnityTest] - public IEnumerator WhenSendingANativeArrayOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new byte[] { byte.MinValue + 5, byte.MaxValue }, Allocator.Persistent), - new NativeArray(new byte[] { 0, byte.MinValue + 10, byte.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(sbyte)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new sbyte[] { sbyte.MinValue + 5, sbyte.MaxValue }, Allocator.Persistent), - new NativeArray(new sbyte[] { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(short)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new short[] { short.MinValue + 5, short.MaxValue }, Allocator.Persistent), - new NativeArray(new short[] { 0, short.MinValue + 10, short.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(ushort)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new ushort[] { ushort.MinValue + 5, ushort.MaxValue }, Allocator.Persistent), - new NativeArray(new ushort[] { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(int)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new int[] { int.MinValue + 5, int.MaxValue }, Allocator.Persistent), - new NativeArray(new int[] { 0, int.MinValue + 10, int.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(uint)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new uint[] { uint.MinValue + 5, uint.MaxValue }, Allocator.Persistent), - new NativeArray(new uint[] { 0, uint.MinValue + 10, uint.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(long)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new long[] { long.MinValue + 5, long.MaxValue }, Allocator.Persistent), - new NativeArray(new long[] { 0, long.MinValue + 10, long.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(ulong)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new ulong[] { ulong.MinValue + 5, ulong.MaxValue }, Allocator.Persistent), - new NativeArray(new ulong[] { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }, Allocator.Persistent)); - } - else if (testType == typeof(bool)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new bool[] { true, false, true }, Allocator.Persistent), - new NativeArray(new bool[] { false, true, false, true, false }, Allocator.Persistent)); - } - else if (testType == typeof(char)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new char[] { 'z', ' ', '?' }, Allocator.Persistent), - new NativeArray(new char[] { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }, Allocator.Persistent)); - } - else if (testType == typeof(float)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new float[] { float.MinValue + 5.12345678f, float.MaxValue }, Allocator.Persistent), - new NativeArray(new float[] { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }, Allocator.Persistent)); - } - else if (testType == typeof(double)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new double[] { double.MinValue + 5.12345678, double.MaxValue }, Allocator.Persistent), - new NativeArray(new double[] { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }, Allocator.Persistent)); - } - else if (testType == typeof(ByteEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new ByteEnum[] { ByteEnum.C, ByteEnum.B, ByteEnum.A }, Allocator.Persistent), - new NativeArray(new ByteEnum[] { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(SByteEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new SByteEnum[] { SByteEnum.C, SByteEnum.B, SByteEnum.A }, Allocator.Persistent), - new NativeArray(new SByteEnum[] { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(ShortEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new ShortEnum[] { ShortEnum.C, ShortEnum.B, ShortEnum.A }, Allocator.Persistent), - new NativeArray(new ShortEnum[] { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(UShortEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new UShortEnum[] { UShortEnum.C, UShortEnum.B, UShortEnum.A }, Allocator.Persistent), - new NativeArray(new UShortEnum[] { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(IntEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new IntEnum[] { IntEnum.C, IntEnum.B, IntEnum.A }, Allocator.Persistent), - new NativeArray(new IntEnum[] { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(UIntEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new UIntEnum[] { UIntEnum.C, UIntEnum.B, UIntEnum.A }, Allocator.Persistent), - new NativeArray(new UIntEnum[] { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(LongEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new LongEnum[] { LongEnum.C, LongEnum.B, LongEnum.A }, Allocator.Persistent), - new NativeArray(new LongEnum[] { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(ULongEnum)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new ULongEnum[] { ULongEnum.C, ULongEnum.B, ULongEnum.A }, Allocator.Persistent), - new NativeArray(new ULongEnum[] { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }, Allocator.Persistent)); - } - else if (testType == typeof(Vector2)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Vector2[] { new Vector2(5, 10), new Vector2(15, 20) }, Allocator.Persistent), - new NativeArray(new Vector2[] { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }, Allocator.Persistent)); - } - else if (testType == typeof(Vector3)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Vector3[] { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, Allocator.Persistent), - new NativeArray(new Vector3[] { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }, Allocator.Persistent)); - } - else if (testType == typeof(Vector2Int)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Vector2Int[] { new Vector2Int(5, 10), new Vector2Int(15, 20) }, Allocator.Persistent), - new NativeArray(new Vector2Int[] { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }, Allocator.Persistent)); - } - else if (testType == typeof(Vector3Int)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Vector3Int[] { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, Allocator.Persistent), - new NativeArray(new Vector3Int[] { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }, Allocator.Persistent)); - } - else if (testType == typeof(Vector4)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Vector4[] { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, Allocator.Persistent), - new NativeArray(new Vector4[] { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }, Allocator.Persistent)); - } - else if (testType == typeof(Quaternion)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Quaternion[] { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, Allocator.Persistent), - new NativeArray(new Quaternion[] { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }, Allocator.Persistent)); - } - else if (testType == typeof(Color)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Color[] { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, Allocator.Persistent), - new NativeArray(new Color[] { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }, Allocator.Persistent)); - } - else if (testType == typeof(Color32)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Color32[] { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, Allocator.Persistent), - new NativeArray(new Color32[] { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }, Allocator.Persistent)); - } - else if (testType == typeof(Ray)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Ray[] - { - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), - }, Allocator.Persistent), - new NativeArray(new Ray[] - { - new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), - new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), - new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), - }, Allocator.Persistent)); - } - else if (testType == typeof(Ray2D)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new Ray2D[] - { - new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), - new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), - }, Allocator.Persistent), - new NativeArray(new Ray2D[] - { - new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), - new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), - new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), - }, Allocator.Persistent)); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, Allocator.Persistent), - new NativeArray(new NetworkVariableTestStruct[] - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, Allocator.Persistent)); - } - else if (testType == typeof(FixedString32Bytes)) - { - yield return TestValueTypeNativeArray( - new NativeArray(new FixedString32Bytes[] - { - new FixedString32Bytes("foobar"), - new FixedString32Bytes("12345678901234567890123456789") - }, Allocator.Persistent), - new NativeArray(new FixedString32Bytes[] - { - new FixedString32Bytes("BazQux"), - new FixedString32Bytes("98765432109876543210987654321"), - new FixedString32Bytes("FixedString32Bytes") - }, Allocator.Persistent)); - } - } - -#if UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT - [UnityTest] - public IEnumerator WhenSendingANativeListOfValueTypesOverAnRpc_ValuesAreSerializedCorrectly( - - [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), - typeof(ByteEnum), typeof(SByteEnum), typeof(ShortEnum), typeof(UShortEnum), typeof(IntEnum), - typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(Vector2), typeof(Vector3), - typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Color), - typeof(Color32), typeof(Ray), typeof(Ray2D), typeof(NetworkVariableTestStruct), typeof(FixedString32Bytes))] - Type testType) - { - if (testType == typeof(byte)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { byte.MinValue + 5, byte.MaxValue }, - new NativeList(Allocator.Persistent) { 0, byte.MinValue + 10, byte.MaxValue - 10 }); - } - else if (testType == typeof(sbyte)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { sbyte.MinValue + 5, sbyte.MaxValue }, - new NativeList(Allocator.Persistent) { 0, sbyte.MinValue + 10, sbyte.MaxValue - 10 }); - } - else if (testType == typeof(short)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { short.MinValue + 5, short.MaxValue }, - new NativeList(Allocator.Persistent) { 0, short.MinValue + 10, short.MaxValue - 10 }); - } - else if (testType == typeof(ushort)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { ushort.MinValue + 5, ushort.MaxValue }, - new NativeList(Allocator.Persistent) { 0, ushort.MinValue + 10, ushort.MaxValue - 10 }); - } - else if (testType == typeof(int)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { int.MinValue + 5, int.MaxValue }, - new NativeList(Allocator.Persistent) { 0, int.MinValue + 10, int.MaxValue - 10 }); - } - else if (testType == typeof(uint)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { uint.MinValue + 5, uint.MaxValue }, - new NativeList(Allocator.Persistent) { 0, uint.MinValue + 10, uint.MaxValue - 10 }); - } - else if (testType == typeof(long)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { long.MinValue + 5, long.MaxValue }, - new NativeList(Allocator.Persistent) { 0, long.MinValue + 10, long.MaxValue - 10 }); - } - else if (testType == typeof(ulong)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { ulong.MinValue + 5, ulong.MaxValue }, - new NativeList(Allocator.Persistent) { 0, ulong.MinValue + 10, ulong.MaxValue - 10 }); - } - else if (testType == typeof(bool)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { true, false, true }, - new NativeList(Allocator.Persistent) { false, true, false, true, false }); - } - else if (testType == typeof(char)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { 'z', ' ', '?' }, - new NativeList(Allocator.Persistent) { 'n', 'e', 'w', ' ', 'v', 'a', 'l', 'u', 'e' }); - } - else if (testType == typeof(float)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { float.MinValue + 5.12345678f, float.MaxValue }, - new NativeList(Allocator.Persistent) { 0, float.MinValue + 10.987654321f, float.MaxValue - 10.135792468f }); - } - else if (testType == typeof(double)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { double.MinValue + 5.12345678, double.MaxValue }, - new NativeList(Allocator.Persistent) { 0, double.MinValue + 10.987654321, double.MaxValue - 10.135792468 }); - } - else if (testType == typeof(ByteEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { ByteEnum.C, ByteEnum.B, ByteEnum.A }, - new NativeList(Allocator.Persistent) { ByteEnum.B, ByteEnum.C, ByteEnum.B, ByteEnum.A, ByteEnum.C }); - } - else if (testType == typeof(SByteEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { SByteEnum.C, SByteEnum.B, SByteEnum.A }, - new NativeList(Allocator.Persistent) { SByteEnum.B, SByteEnum.C, SByteEnum.B, SByteEnum.A, SByteEnum.C }); - } - else if (testType == typeof(ShortEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { ShortEnum.C, ShortEnum.B, ShortEnum.A }, - new NativeList(Allocator.Persistent) { ShortEnum.B, ShortEnum.C, ShortEnum.B, ShortEnum.A, ShortEnum.C }); - } - else if (testType == typeof(UShortEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { UShortEnum.C, UShortEnum.B, UShortEnum.A }, - new NativeList(Allocator.Persistent) { UShortEnum.B, UShortEnum.C, UShortEnum.B, UShortEnum.A, UShortEnum.C }); - } - else if (testType == typeof(IntEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { IntEnum.C, IntEnum.B, IntEnum.A }, - new NativeList(Allocator.Persistent) { IntEnum.B, IntEnum.C, IntEnum.B, IntEnum.A, IntEnum.C }); - } - else if (testType == typeof(UIntEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { UIntEnum.C, UIntEnum.B, UIntEnum.A }, - new NativeList(Allocator.Persistent) { UIntEnum.B, UIntEnum.C, UIntEnum.B, UIntEnum.A, UIntEnum.C }); - } - else if (testType == typeof(LongEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { LongEnum.C, LongEnum.B, LongEnum.A }, - new NativeList(Allocator.Persistent) { LongEnum.B, LongEnum.C, LongEnum.B, LongEnum.A, LongEnum.C }); - } - else if (testType == typeof(ULongEnum)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { ULongEnum.C, ULongEnum.B, ULongEnum.A }, - new NativeList(Allocator.Persistent) { ULongEnum.B, ULongEnum.C, ULongEnum.B, ULongEnum.A, ULongEnum.C }); - } - else if (testType == typeof(Vector2)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Vector2(5, 10), new Vector2(15, 20) }, - new NativeList(Allocator.Persistent) { new Vector2(25, 30), new Vector2(35, 40), new Vector2(45, 50) }); - } - else if (testType == typeof(Vector3)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Vector3(5, 10, 15), new Vector3(20, 25, 30) }, - new NativeList(Allocator.Persistent) { new Vector3(35, 40, 45), new Vector3(50, 55, 60), new Vector3(65, 70, 75) }); - } - else if (testType == typeof(Vector2Int)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Vector2Int(5, 10), new Vector2Int(15, 20) }, - new NativeList(Allocator.Persistent) { new Vector2Int(25, 30), new Vector2Int(35, 40), new Vector2Int(45, 50) }); - } - else if (testType == typeof(Vector3Int)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Vector3Int(5, 10, 15), new Vector3Int(20, 25, 30) }, - new NativeList(Allocator.Persistent) { new Vector3Int(35, 40, 45), new Vector3Int(50, 55, 60), new Vector3Int(65, 70, 75) }); - } - else if (testType == typeof(Vector4)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Vector4(5, 10, 15, 20), new Vector4(25, 30, 35, 40) }, - new NativeList(Allocator.Persistent) { new Vector4(45, 50, 55, 60), new Vector4(65, 70, 75, 80), new Vector4(85, 90, 95, 100) }); - } - else if (testType == typeof(Quaternion)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Quaternion(5, 10, 15, 20), new Quaternion(25, 30, 35, 40) }, - new NativeList(Allocator.Persistent) { new Quaternion(45, 50, 55, 60), new Quaternion(65, 70, 75, 80), new Quaternion(85, 90, 95, 100) }); - } - else if (testType == typeof(Color)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Color(.5f, .10f, .15f), new Color(.20f, .25f, .30f) }, - new NativeList(Allocator.Persistent) { new Color(.35f, .40f, .45f), new Color(.50f, .55f, .60f), new Color(.65f, .70f, .75f) }); - } - else if (testType == typeof(Color32)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) { new Color32(5, 10, 15, 20), new Color32(25, 30, 35, 40) }, - new NativeList(Allocator.Persistent) { new Color32(45, 50, 55, 60), new Color32(65, 70, 75, 80), new Color32(85, 90, 95, 100) }); - } - else if (testType == typeof(Ray)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) - { - new Ray(new Vector3(0, 1, 2), new Vector3(3, 4, 5)), - new Ray(new Vector3(6, 7, 8), new Vector3(9, 10, 11)), - }, - new NativeList(Allocator.Persistent) - { - new Ray(new Vector3(12, 13, 14), new Vector3(15, 16, 17)), - new Ray(new Vector3(18, 19, 20), new Vector3(21, 22, 23)), - new Ray(new Vector3(24, 25, 26), new Vector3(27, 28, 29)), - }); - } - else if (testType == typeof(Ray2D)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) - { - new Ray2D(new Vector2(0, 1), new Vector2(3, 4)), - new Ray2D(new Vector2(6, 7), new Vector2(9, 10)), - }, - new NativeList(Allocator.Persistent) - { - new Ray2D(new Vector2(12, 13), new Vector2(15, 16)), - new Ray2D(new Vector2(18, 19), new Vector2(21, 22)), - new Ray2D(new Vector2(24, 25), new Vector2(27, 28)), - }); - } - else if (testType == typeof(NetworkVariableTestStruct)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }, - new NativeList(Allocator.Persistent) - { - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct(), - NetworkVariableTestStruct.GetTestStruct() - }); - } - else if (testType == typeof(FixedString32Bytes)) - { - yield return TestValueTypeNativeList( - new NativeList(Allocator.Persistent) - { - new FixedString32Bytes("foobar"), - new FixedString32Bytes("12345678901234567890123456789") - }, - new NativeList(Allocator.Persistent) - { - new FixedString32Bytes("BazQux"), - new FixedString32Bytes("98765432109876543210987654321"), - new FixedString32Bytes("FixedString32Bytes") - }); - } - } -#endif - } -} diff --git a/Tests/Runtime/RpcTypeSerializationTests.cs.meta b/Tests/Runtime/RpcTypeSerializationTests.cs.meta deleted file mode 100644 index a0a88af..0000000 --- a/Tests/Runtime/RpcTypeSerializationTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: fd1b9e10285844d48c86d1930652d22c -timeCreated: 1672959718 \ No newline at end of file diff --git a/Tests/Runtime/Serialization.meta b/Tests/Runtime/Serialization.meta deleted file mode 100644 index 1f1dc0f..0000000 --- a/Tests/Runtime/Serialization.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 90d51da7691e302498265bba08c43636 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs b/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs deleted file mode 100644 index 6b7d497..0000000 --- a/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Unit tests to test: - /// - Serializing NetworkObject to NetworkObjectReference - /// - Deserializing NetworkObjectReference to NetworkObject - /// - Implicit operators of NetworkObjectReference - /// - internal class NetworkBehaviourReferenceTests : IDisposable - { - private class TestNetworkBehaviour : NetworkBehaviour - { - public static bool ReceivedRPC; - - public NetworkVariable TestVariable = new NetworkVariable(); - - public TestNetworkBehaviour RpcReceivedBehaviour; - - [ServerRpc] - public void SendReferenceServerRpc(NetworkBehaviourReference value) - { - RpcReceivedBehaviour = (TestNetworkBehaviour)value; - ReceivedRPC = true; - } - } - - [UnityTest] - public IEnumerator TestRpc() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - testNetworkBehaviour.SendReferenceServerRpc(new NetworkBehaviourReference(testNetworkBehaviour)); - - // wait for rpc completion - float t = 0; - while (testNetworkBehaviour.RpcReceivedBehaviour == null) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(testNetworkBehaviour, testNetworkBehaviour.RpcReceivedBehaviour); - } - - [UnityTest] - public IEnumerator TestSerializeNull([Values] bool initializeWithNull) - { - TestNetworkBehaviour.ReceivedRPC = false; - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - // If not initializing with null, then use the default constructor with no assigned NetworkBehaviour - if (!initializeWithNull) - { - testNetworkBehaviour.SendReferenceServerRpc(new NetworkBehaviourReference()); - } - else // Otherwise, initialize and pass in null as the reference - { - testNetworkBehaviour.SendReferenceServerRpc(new NetworkBehaviourReference(null)); - } - - // wait for rpc completion - float t = 0; - while (!TestNetworkBehaviour.ReceivedRPC) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(null, testNetworkBehaviour.RpcReceivedBehaviour); - } - - [UnityTest] - public IEnumerator TestRpcImplicitNetworkBehaviour() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - testNetworkBehaviour.SendReferenceServerRpc(testNetworkBehaviour); - - // wait for rpc completion - float t = 0; - while (testNetworkBehaviour.RpcReceivedBehaviour == null) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(testNetworkBehaviour, testNetworkBehaviour.RpcReceivedBehaviour); - } - - [Test] - public void TestNetworkVariable() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - // check default value is null - Assert.IsNull((NetworkBehaviour)testNetworkBehaviour.TestVariable.Value); - - testNetworkBehaviour.TestVariable.Value = testNetworkBehaviour; - - Assert.AreEqual((NetworkBehaviour)testNetworkBehaviour.TestVariable.Value, testNetworkBehaviour); - } - - [Test] - public void FailSerializeNonSpawnedNetworkObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var component = networkObjectContext.Object.gameObject.AddComponent(); - - Assert.Throws(() => - { - NetworkBehaviourReference outReference = component; - }); - } - - [Test] - public void FailSerializeGameObjectWithoutNetworkObject() - { - using var gameObjectContext = UnityObjectContext.CreateGameObject(); - var component = gameObjectContext.Object.gameObject.AddComponent(); - - Assert.Throws(() => - { - NetworkBehaviourReference outReference = component; - }); - } - - public void Dispose() - { - //Stop, shutdown, and destroy - NetworkManagerHelper.ShutdownNetworkManager(); - } - - public NetworkBehaviourReferenceTests() - { - //Create, instantiate, and host - NetworkManagerHelper.StartNetworkManager(out _); - } - } - - /// - /// Integration tests for NetworkBehaviourReference - /// - internal class NetworkBehaviourReferenceIntegrationTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - internal class FakeMissingComponent : NetworkBehaviour - { - - } - - internal class TestAddedComponent : NetworkBehaviour - { - - } - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - base.OnCreatePlayerPrefab(); - } - - /// - /// This test validates that if a component does not exist the NetworkBehaviourReference will not throw an - /// invalid cast exception. - /// (It is a full integration test to assure the NetworkObjects are spawned) - /// - [UnityTest] - public IEnumerator TestTryGetWithAndWithOutExistingComponent() - { - var networkBehaviourReference = new NetworkBehaviourReference(m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent()); - var missingComponent = (FakeMissingComponent)null; - var testBehaviour = (TestAddedComponent)null; - Assert.IsFalse(networkBehaviourReference.TryGet(out missingComponent)); - Assert.IsTrue(networkBehaviourReference.TryGet(out testBehaviour)); - yield return null; - } - } -} diff --git a/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs.meta b/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs.meta deleted file mode 100644 index 6ae11f3..0000000 --- a/Tests/Runtime/Serialization/NetworkBehaviourReferenceTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0fca807d195f9fc49a400cfce86b085d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs b/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs deleted file mode 100644 index ab347f4..0000000 --- a/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs +++ /dev/null @@ -1,422 +0,0 @@ -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Unit tests to test: - /// - Serializing NetworkObject to NetworkObjectReference - /// - Deserializing NetworkObjectReference to NetworkObject - /// - Implicit operators of NetworkObjectReference - /// - internal class NetworkObjectReferenceTests : IDisposable - { - private class TestNetworkBehaviour : NetworkBehaviour - { - public static bool ReceivedRPC; - - public NetworkVariable TestVariable = new NetworkVariable(); - - public NetworkObject RpcReceivedNetworkObject; - - public GameObject RpcReceivedGameObject; - - [ServerRpc] - public void SendReferenceServerRpc(NetworkObjectReference value) - { - ReceivedRPC = true; - RpcReceivedGameObject = value; - RpcReceivedNetworkObject = value; - } - } - - [Test] - public void TestSerializeNetworkObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - var outWriter = new FastBufferWriter(1300, Allocator.Temp); - try - { - // serialize - var outSerializer = new BufferSerializer(new BufferSerializerWriter(outWriter)); - NetworkObjectReference outReference = networkObjectContext.Object; - outReference.NetworkSerialize(outSerializer); - - // deserialize - NetworkObjectReference inReference = default; - var inReader = new FastBufferReader(outWriter, Allocator.Temp); - try - { - var inSerializer = - new BufferSerializer(new BufferSerializerReader(inReader)); - inReference.NetworkSerialize(inSerializer); - } - finally - { - inReader.Dispose(); - } - - // validate - Assert.NotNull((NetworkObject)inReference); - Assert.AreEqual(inReference.NetworkObjectId, networkObjectContext.Object.NetworkObjectId); - Assert.AreEqual(outReference, inReference); - Assert.AreEqual(networkObjectContext.Object, (NetworkObject)inReference); - } - finally - { - outWriter.Dispose(); - } - } - - [Test] - public void TestSerializeGameObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - var outWriter = new FastBufferWriter(1300, Allocator.Temp); - try - { - // serialize - var outSerializer = new BufferSerializer(new BufferSerializerWriter(outWriter)); - NetworkObjectReference outReference = networkObjectContext.Object.gameObject; - outReference.NetworkSerialize(outSerializer); - - // deserialize - NetworkObjectReference inReference = default; - var inReader = new FastBufferReader(outWriter, Allocator.Temp); - try - { - var inSerializer = - new BufferSerializer(new BufferSerializerReader(inReader)); - inReference.NetworkSerialize(inSerializer); - } - finally - { - inReader.Dispose(); - } - GameObject gameObject = inReference; - - // validate - Assert.AreEqual(outReference, inReference); - Assert.AreEqual(networkObjectContext.Object.gameObject, gameObject); - } - finally - { - outWriter.Dispose(); - } - } - - [Test] - public void TestImplicitConversionToGameObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - - NetworkObjectReference outReference = networkObjectContext.Object.gameObject; - - GameObject go = outReference; - Assert.AreEqual(networkObjectContext.Object.gameObject, go); - } - - [Test] - public void TestImplicitToGameObjectIsNullWhenNotFound() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - - NetworkObjectReference outReference = networkObjectContext.Object.gameObject; - - networkObjectContext.Object.Despawn(); - Object.DestroyImmediate(networkObjectContext.Object.gameObject); - - GameObject go = outReference; - Assert.IsNull(go); - } - [Test] - public void TestTryGet() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - - NetworkObjectReference networkObjectReference = networkObjectContext.Object; - - Assert.True(networkObjectReference.TryGet(out NetworkObject networkObject)); - Assert.NotNull(networkObject); - networkObjectReference.TryGet(out NetworkObject result); - Assert.AreEqual(networkObject, result); - } - - public enum NetworkObjectConstructorTypes - { - None, - NullNetworkObject, - NullGameObject - } - - [UnityTest] - public IEnumerator TestSerializeNull([Values] NetworkObjectConstructorTypes networkObjectConstructorTypes) - { - TestNetworkBehaviour.ReceivedRPC = false; - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - switch (networkObjectConstructorTypes) - { - case NetworkObjectConstructorTypes.None: - { - testNetworkBehaviour.SendReferenceServerRpc(new NetworkObjectReference()); - break; - } - case NetworkObjectConstructorTypes.NullNetworkObject: - { - testNetworkBehaviour.SendReferenceServerRpc(new NetworkObjectReference((NetworkObject)null)); - break; - } - case NetworkObjectConstructorTypes.NullGameObject: - { - testNetworkBehaviour.SendReferenceServerRpc(new NetworkObjectReference((GameObject)null)); - break; - } - } - - - // wait for rpc completion - float t = 0; - while (!TestNetworkBehaviour.ReceivedRPC) - { - - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(null, testNetworkBehaviour.RpcReceivedNetworkObject); - Assert.AreEqual(null, testNetworkBehaviour.RpcReceivedGameObject); - } - - [UnityTest] - public IEnumerator TestRpc() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - testNetworkBehaviour.SendReferenceServerRpc(new NetworkObjectReference(otherObjectContext.Object)); - - // wait for rpc completion - float t = 0; - while (testNetworkBehaviour.RpcReceivedGameObject == null) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(otherObjectContext.Object, testNetworkBehaviour.RpcReceivedNetworkObject); - Assert.AreEqual(otherObjectContext.Object.gameObject, testNetworkBehaviour.RpcReceivedGameObject); - } - - [UnityTest] - public IEnumerator TestRpcImplicitNetworkObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - testNetworkBehaviour.SendReferenceServerRpc(otherObjectContext.Object); - - // wait for rpc completion - float t = 0; - while (testNetworkBehaviour.RpcReceivedGameObject == null) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(otherObjectContext.Object, testNetworkBehaviour.RpcReceivedNetworkObject); - Assert.AreEqual(otherObjectContext.Object.gameObject, testNetworkBehaviour.RpcReceivedGameObject); - } - - [UnityTest] - public IEnumerator TestRpcImplicitGameObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - testNetworkBehaviour.SendReferenceServerRpc(otherObjectContext.Object.gameObject); - - // wait for rpc completion - float t = 0; - while (testNetworkBehaviour.RpcReceivedGameObject == null) - { - t += Time.deltaTime; - if (t > 5f) - { - new AssertionException("RPC with NetworkBehaviour reference hasn't been received"); - } - - yield return null; - } - - // validate - Assert.AreEqual(otherObjectContext.Object, testNetworkBehaviour.RpcReceivedNetworkObject); - Assert.AreEqual(otherObjectContext.Object.gameObject, testNetworkBehaviour.RpcReceivedGameObject); - } - - [Test] - public void TestNetworkVariable() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - var testNetworkBehaviour = networkObjectContext.Object.gameObject.AddComponent(); - networkObjectContext.Object.Spawn(); - - using var otherObjectContext = UnityObjectContext.CreateNetworkObject(); - otherObjectContext.Object.Spawn(); - - // check default value is null - Assert.IsNull((NetworkObject)testNetworkBehaviour.TestVariable.Value); - - testNetworkBehaviour.TestVariable.Value = networkObjectContext.Object; - - Assert.AreEqual((GameObject)testNetworkBehaviour.TestVariable.Value, networkObjectContext.Object.gameObject); - Assert.AreEqual((NetworkObject)testNetworkBehaviour.TestVariable.Value, networkObjectContext.Object); - } - - [Test] - public void TestDespawn() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - networkObjectContext.Object.Spawn(); - var originalId = networkObjectContext.Object.NetworkObjectId; - - NetworkObjectReference networkObjectReference = networkObjectContext.Object; - Assert.AreEqual(networkObjectContext.Object, (NetworkObject)networkObjectReference); - - networkObjectContext.Object.Despawn(); - Assert.IsFalse(networkObjectReference.TryGet(out NetworkObject _)); - - networkObjectContext.Object.Spawn(); - - // After spawning again the reference will still no longer work as it still points to the old object - Assert.AreNotEqual(originalId, networkObjectContext.Object.NetworkObjectId); - Assert.IsFalse(networkObjectReference.TryGet(out NetworkObject _)); - - // creating a new reference will make it work again - networkObjectReference = networkObjectContext.Object; - Assert.AreEqual(networkObjectContext.Object, (NetworkObject)networkObjectReference); - } - - [Test] - public void FailSerializeNonSpawnedNetworkObject() - { - using var networkObjectContext = UnityObjectContext.CreateNetworkObject(); - - Assert.Throws(() => - { - NetworkObjectReference outReference = networkObjectContext.Object; - }); - } - - [Test] - public void FailSerializeGameObjectWithoutNetworkObject() - { - using var gameObjectContext = UnityObjectContext.CreateGameObject(); - - Assert.Throws(() => - { - NetworkObjectReference outReference = gameObjectContext.Object; - }); - } - - public void Dispose() - { - //Stop, shutdown, and destroy - NetworkManagerHelper.ShutdownNetworkManager(); - } - - public NetworkObjectReferenceTests() - { - //Create, instantiate, and host - NetworkManagerHelper.StartNetworkManager(out _); - } - } - - /// - /// Helper method for tests to create and destroy Unity Objects. - /// - /// The type of Object this context incorporates. - internal class UnityObjectContext : UnityObjectContext where T : Object - { - private T m_Object; - - internal UnityObjectContext(T unityObject, Object root) - : base(root) - { - m_Object = unityObject; - } - - public T Object => m_Object; - } - - internal class UnityObjectContext : IDisposable - { - private Object m_Root; - - protected UnityObjectContext(Object root) - { - m_Root = root; - } - - public static UnityObjectContext CreateGameObject(string name = "") - { - var gameObject = new GameObject(name); - return new UnityObjectContext(gameObject, gameObject); - } - - public static UnityObjectContext CreateNetworkObject(string name = "") - { - var gameObject = new GameObject(name); - var networkObject = gameObject.AddComponent(); - return new UnityObjectContext(networkObject, gameObject); - } - - public void Dispose() - { - Object.DestroyImmediate(m_Root); - } - } -} diff --git a/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs.meta b/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs.meta deleted file mode 100644 index bcaad14..0000000 --- a/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 182c2000b73248b4bbdd79f70ec90cd2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/StartStopTests.cs b/Tests/Runtime/StartStopTests.cs deleted file mode 100644 index bb928e1..0000000 --- a/Tests/Runtime/StartStopTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using NUnit.Framework; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class StartStopTests - { - private NetworkManager m_NetworkManager; - - [SetUp] - public void Setup() - { - // Create the reusable NetworkManager - m_NetworkManager = new GameObject(nameof(NetworkManager)).AddComponent(); - var transport = m_NetworkManager.gameObject.AddComponent(); - - m_NetworkManager.NetworkConfig = new NetworkConfig() - { - NetworkTransport = transport - }; - } - - [Test] - public void TestStopAndRestartForExceptions() - { - m_NetworkManager.StartServer(); - m_NetworkManager.Shutdown(); - m_NetworkManager.StartServer(); - m_NetworkManager.Shutdown(); - } - - [Test] - public void TestStartupServerState() - { - m_NetworkManager.StartServer(); - - Assert.True(m_NetworkManager.IsServer); - Assert.False(m_NetworkManager.IsClient); - Assert.False(m_NetworkManager.IsHost); - - m_NetworkManager.Shutdown(); - } - - [Test] - public void TestFlagShutdown() - { - m_NetworkManager.StartServer(); - m_NetworkManager.ShutdownInternal(); - - Assert.False(m_NetworkManager.IsServer); - Assert.False(m_NetworkManager.IsClient); - Assert.False(m_NetworkManager.IsHost); - } - - [Test] - public void TestShutdownWithoutStartForExceptions() - { - m_NetworkManager.ShutdownInternal(); - } - - [Test] - public void TestShutdownWithoutConfigForExceptions() - { - m_NetworkManager.NetworkConfig = null; - m_NetworkManager.ShutdownInternal(); - } - - [TearDown] - public void Teardown() - { - // Cleanup - Object.DestroyImmediate(m_NetworkManager.gameObject); - } - } -} diff --git a/Tests/Runtime/StartStopTests.cs.meta b/Tests/Runtime/StartStopTests.cs.meta deleted file mode 100644 index 6aee4cc..0000000 --- a/Tests/Runtime/StartStopTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e8e36047cb5542bcaade2a9a8746d713 -timeCreated: 1630336158 \ No newline at end of file diff --git a/Tests/Runtime/StopStartRuntimeTests.cs b/Tests/Runtime/StopStartRuntimeTests.cs deleted file mode 100644 index 8ec1c37..0000000 --- a/Tests/Runtime/StopStartRuntimeTests.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - internal class StopStartRuntimeTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - protected override void OnOneTimeSetup() - { - m_UseHost = false; - base.OnOneTimeSetup(); - } - - - private bool m_ServerStopped; - [UnityTest] - public IEnumerator WhenShuttingDownAndRestarting_SDKRestartsSuccessfullyAndStaysRunning() - { - // shutdown the server - m_ServerNetworkManager.OnServerStopped += OnServerStopped; - m_ServerNetworkManager.Shutdown(); - - // wait until the OnServerStopped is invoked - m_ServerStopped = false; - yield return WaitForConditionOrTimeOut(() => m_ServerStopped); - AssertOnTimeout("Timed out waiting for the server to stop!"); - - // Verify the shutdown occurred - Assert.IsFalse(m_ServerNetworkManager.IsServer); - Assert.IsFalse(m_ServerNetworkManager.IsListening); - Assert.IsFalse(m_ServerNetworkManager.IsHost); - Assert.IsFalse(m_ServerNetworkManager.IsClient); - - m_ServerNetworkManager.StartServer(); - // Verify the server started - Assert.IsTrue(m_ServerNetworkManager.IsServer); - Assert.IsTrue(m_ServerNetworkManager.IsListening); - - // Wait several frames / one full network tick - yield return s_DefaultWaitForTick; - - // Verify the server is still running - Assert.IsTrue(m_ServerNetworkManager.IsServer); - Assert.IsTrue(m_ServerNetworkManager.IsListening); - } - - private void OnServerStopped(bool obj) - { - m_ServerNetworkManager.OnServerStopped -= OnServerStopped; - m_ServerStopped = true; - } - - [UnityTest] - public IEnumerator WhenShuttingDownTwiceAndRestarting_SDKRestartsSuccessfullyAndStaysRunning() - { - // shutdown the server - m_ServerNetworkManager.OnServerStopped += OnServerStopped; - m_ServerNetworkManager.Shutdown(); - - // wait until the OnServerStopped is invoked - m_ServerStopped = false; - yield return WaitForConditionOrTimeOut(() => m_ServerStopped); - AssertOnTimeout("Timed out waiting for the server to stop!"); - - // Verify the shutdown occurred - Assert.IsFalse(m_ServerNetworkManager.IsServer); - Assert.IsFalse(m_ServerNetworkManager.IsListening); - Assert.IsFalse(m_ServerNetworkManager.IsHost); - Assert.IsFalse(m_ServerNetworkManager.IsClient); - - // Shutdown the server again. - m_ServerNetworkManager.Shutdown(); - - m_ServerNetworkManager.StartServer(); - // Verify the server started - Assert.IsTrue(m_ServerNetworkManager.IsServer); - Assert.IsTrue(m_ServerNetworkManager.IsListening); - - // Wait several frames / one full network tick - yield return s_DefaultWaitForTick; - - // Verify the server is still running - Assert.IsTrue(m_ServerNetworkManager.IsServer); - Assert.IsTrue(m_ServerNetworkManager.IsListening); - } - } -} diff --git a/Tests/Runtime/StopStartRuntimeTests.cs.meta b/Tests/Runtime/StopStartRuntimeTests.cs.meta deleted file mode 100644 index 8df3e77..0000000 --- a/Tests/Runtime/StopStartRuntimeTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 97a5298e33ee4d32be46ce84fecdcd06 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/TestHelpers.meta b/Tests/Runtime/TestHelpers.meta deleted file mode 100644 index ce3ac00..0000000 --- a/Tests/Runtime/TestHelpers.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1f398e1797944b5db4d3aa473629f46e -timeCreated: 1661800773 \ No newline at end of file diff --git a/Tests/Runtime/TestHelpers/MessageCatcher.cs b/Tests/Runtime/TestHelpers/MessageCatcher.cs deleted file mode 100644 index f408532..0000000 --- a/Tests/Runtime/TestHelpers/MessageCatcher.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using Unity.Collections; - -namespace Unity.Netcode.RuntimeTests -{ - internal class MessageCatcher : INetworkHooks where TMessageType : INetworkMessage - { - private NetworkManager m_OwnerNetworkManager; - - public MessageCatcher(NetworkManager ownerNetworkManager) - { - m_OwnerNetworkManager = ownerNetworkManager; - } - - private struct TriggerData - { - public FastBufferReader Reader; - public NetworkMessageHeader Header; - public ulong SenderId; - public float Timestamp; - public int SerializedHeaderSize; - } - private readonly List m_CaughtMessages = new List(); - - public void ReleaseMessages() - { - - foreach (var caughtSpawn in m_CaughtMessages) - { - // Reader will be disposed within HandleMessage - m_OwnerNetworkManager.ConnectionManager.MessageManager.HandleMessage(caughtSpawn.Header, caughtSpawn.Reader, caughtSpawn.SenderId, caughtSpawn.Timestamp, caughtSpawn.SerializedHeaderSize); - } - } - - public int CaughtMessageCount => m_CaughtMessages.Count; - - public void OnBeforeSendMessage(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage - { - } - - public void OnAfterSendMessage(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage - { - } - - public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - public void OnAfterReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - public void OnBeforeSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - public void OnAfterSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - public void OnBeforeReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - public void OnAfterReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - public bool OnVerifyCanSend(ulong destinationId, Type messageType, NetworkDelivery delivery) - { - return true; - } - - public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReader messageContent, ref NetworkContext context) - { - if (messageType == typeof(TMessageType)) - { - m_CaughtMessages.Add(new TriggerData - { - Reader = new FastBufferReader(messageContent, Allocator.Persistent), - Header = context.Header, - Timestamp = context.Timestamp, - SenderId = context.SenderId, - SerializedHeaderSize = context.SerializedHeaderSize - }); - return false; - } - - return true; - } - - public void OnBeforeHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - - public void OnAfterHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - } -} diff --git a/Tests/Runtime/TestHelpers/MessageCatcher.cs.meta b/Tests/Runtime/TestHelpers/MessageCatcher.cs.meta deleted file mode 100644 index 93a0c6f..0000000 --- a/Tests/Runtime/TestHelpers/MessageCatcher.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f008d074bcb841ae90b1949f9e2f0854 -timeCreated: 1661796973 \ No newline at end of file diff --git a/Tests/Runtime/TestHelpers/MessageLogger.cs b/Tests/Runtime/TestHelpers/MessageLogger.cs deleted file mode 100644 index 3ed7ac3..0000000 --- a/Tests/Runtime/TestHelpers/MessageLogger.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal class MessageLogger : INetworkHooks - { - private NetworkManager m_OwningNetworkManager; - public MessageLogger(NetworkManager owningNetworkManager) - { - m_OwningNetworkManager = owningNetworkManager; - } - - public void OnBeforeSendMessage(ulong clientId, ref T message, NetworkDelivery delivery) where T : INetworkMessage - { - Debug.Log($"{(m_OwningNetworkManager.IsServer ? "Server" : "Client")} {m_OwningNetworkManager.LocalClientId}: Sending {message.GetType().FullName} to {clientId} with {delivery}"); - } - - public void OnAfterSendMessage(ulong clientId, ref T message, NetworkDelivery delivery, int messageSizeBytes) where T : INetworkMessage - { - } - - public void OnBeforeReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - Debug.Log($"{(m_OwningNetworkManager.IsServer ? "Server" : "Client")} {m_OwningNetworkManager.LocalClientId}: Receiving {messageType.FullName} from {senderId}"); - } - - public void OnAfterReceiveMessage(ulong senderId, Type messageType, int messageSizeBytes) - { - } - - public void OnBeforeSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - Debug.Log($"{(m_OwningNetworkManager.IsServer ? "Server" : "Client")} {m_OwningNetworkManager.LocalClientId}: Sending a batch of to {clientId}: {messageCount} messages, {batchSizeInBytes} bytes, with {delivery}"); - } - - public void OnAfterSendBatch(ulong clientId, int messageCount, int batchSizeInBytes, NetworkDelivery delivery) - { - } - - public void OnBeforeReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - Debug.Log($"{(m_OwningNetworkManager.IsServer ? "Server" : "Client")} {m_OwningNetworkManager.LocalClientId}: Received a batch from {senderId}, {messageCount} messages, {batchSizeInBytes} bytes"); - } - - public void OnAfterReceiveBatch(ulong senderId, int messageCount, int batchSizeInBytes) - { - } - - public bool OnVerifyCanSend(ulong destinationId, Type messageType, NetworkDelivery delivery) - { - return true; - } - - public bool OnVerifyCanReceive(ulong senderId, Type messageType, FastBufferReader messageContent, ref NetworkContext context) - { - return true; - } - - public void OnBeforeHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - Debug.Log($"{(m_OwningNetworkManager.IsServer ? "Server" : "Client")} {m_OwningNetworkManager.LocalClientId}: Handling message {message.GetType().FullName}"); - } - - public void OnAfterHandleMessage(ref T message, ref NetworkContext context) where T : INetworkMessage - { - } - } -} diff --git a/Tests/Runtime/TestHelpers/MessageLogger.cs.meta b/Tests/Runtime/TestHelpers/MessageLogger.cs.meta deleted file mode 100644 index 290d149..0000000 --- a/Tests/Runtime/TestHelpers/MessageLogger.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 4dbf404fdf544a409bf1bcab2c3f8b3e -timeCreated: 1661799489 \ No newline at end of file diff --git a/Tests/Runtime/Timing.meta b/Tests/Runtime/Timing.meta deleted file mode 100644 index fa4107a..0000000 --- a/Tests/Runtime/Timing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: db225cab5067aae4e8b7771af8a4183c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Timing/NetworkTimeSystemTests.cs b/Tests/Runtime/Timing/NetworkTimeSystemTests.cs deleted file mode 100644 index c38bc86..0000000 --- a/Tests/Runtime/Timing/NetworkTimeSystemTests.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.Assertions.Comparers; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Runtime tests to test the network time system with the Unity player loop. - /// - internal class NetworkTimeSystemTests - { - private MonoBehaviourTest m_PlayerLoopFixedTimeTestComponent; // cache for teardown - private MonoBehaviourTest m_PlayerLoopTimeTestComponent; // cache for teardown - - private float m_OriginalTimeScale = 1.0f; - - [SetUp] - public void Setup() - { - m_OriginalTimeScale = Time.timeScale; - - // Create, instantiate, and host - Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _)); - } - - /// - /// Tests whether time is accessible and has correct values inside Update/FixedUpdate. - /// This test applies only when is 1. - /// - /// - [UnityTest] - public IEnumerator PlayerLoopFixedTimeTest() - { - m_PlayerLoopFixedTimeTestComponent = new MonoBehaviourTest(); - - yield return m_PlayerLoopFixedTimeTestComponent; - } - - /// - /// Tests whether time is accessible and has correct values inside Update, for multiples values. - /// - /// - [UnityTest] - public IEnumerator PlayerLoopTimeTest_WithDifferentTimeScale([Values(0.0f, 0.1f, 0.5f, 1.0f, 2.0f, 5.0f)] float timeScale) - { - Time.timeScale = timeScale; - - m_PlayerLoopTimeTestComponent = new MonoBehaviourTest(); - - yield return m_PlayerLoopTimeTestComponent; - } - - /// - /// Tests whether the time system invokes the correct amount of ticks over a period of time. - /// Note we cannot test against Time.Time directly because of floating point precision. Our time is more precise leading to different results. - /// - /// - [UnityTest] - public IEnumerator CorrectAmountTicksTest() - { - NetworkTickSystem tickSystem = NetworkManager.Singleton.NetworkTickSystem; - float delta = tickSystem.LocalTime.FixedDeltaTime; - int previous_localTickCalculated = 0; - int previous_serverTickCalculated = 0; - - while (tickSystem.LocalTime.Time < 3f) - { - yield return null; - - var tickCalculated = tickSystem.LocalTime.Time / delta; - previous_localTickCalculated = (int)tickCalculated; - - // This check is needed due to double division imprecision of large numbers - if ((tickCalculated - previous_localTickCalculated) >= 0.999999999999) - { - previous_localTickCalculated++; - } - - - tickCalculated = NetworkManager.Singleton.ServerTime.Time / delta; - previous_serverTickCalculated = (int)tickCalculated; - - // This check is needed due to double division imprecision of large numbers - if ((tickCalculated - previous_serverTickCalculated) >= 0.999999999999) - { - previous_serverTickCalculated++; - } - - Assert.AreEqual(previous_localTickCalculated, NetworkManager.Singleton.LocalTime.Tick, $"Calculated local tick {previous_localTickCalculated} does not match local tick {NetworkManager.Singleton.LocalTime.Tick}!"); - Assert.AreEqual(previous_serverTickCalculated, NetworkManager.Singleton.ServerTime.Tick, $"Calculated server tick {previous_serverTickCalculated} does not match server tick {NetworkManager.Singleton.ServerTime.Tick}!"); - Assert.AreEqual((float)NetworkManager.Singleton.LocalTime.Time, (float)NetworkManager.Singleton.ServerTime.Time, $"Local time {(float)NetworkManager.Singleton.LocalTime.Time} is not approximately server time {(float)NetworkManager.Singleton.ServerTime.Time}!", FloatComparer.s_ComparerWithDefaultTolerance); - } - } - - [TearDown] - public void TearDown() - { - // Stop, shutdown, and destroy - NetworkManagerHelper.ShutdownNetworkManager(); - - Time.timeScale = m_OriginalTimeScale; - - if (m_PlayerLoopFixedTimeTestComponent != null) - { - Object.DestroyImmediate(m_PlayerLoopFixedTimeTestComponent.gameObject); - m_PlayerLoopFixedTimeTestComponent = null; - } - - if (m_PlayerLoopTimeTestComponent != null) - { - Object.DestroyImmediate(m_PlayerLoopTimeTestComponent.gameObject); - m_PlayerLoopTimeTestComponent = null; - } - } - } - - internal class PlayerLoopFixedTimeTestComponent : MonoBehaviour, IMonoBehaviourTest - { - public const int Passes = 100; - - private int m_UpdatePasses = 0; - - private int m_LastFixedUpdateTick = 0; - private int m_TickOffset = -1; - - private NetworkTime m_LocalTimePreviousUpdate; - private NetworkTime m_ServerTimePreviousUpdate; - private NetworkTime m_LocalTimePreviousFixedUpdate; - - private void Start() - { - // Run fixed update at same rate as network tick - Time.fixedDeltaTime = NetworkManager.Singleton.LocalTime.FixedDeltaTime; - - // Uncap fixed time else we might skip fixed updates - Time.maximumDeltaTime = float.MaxValue; - } - - private void Update() - { - // This must run first else it wont run if there is an exception - m_UpdatePasses++; - - NetworkTime localTime = NetworkManager.Singleton.LocalTime; - NetworkTime serverTime = NetworkManager.Singleton.ServerTime; - - // time should have advanced on the host/server - Assert.Less(m_LocalTimePreviousUpdate.Time, localTime.Time); - Assert.Less(m_ServerTimePreviousUpdate.Time, serverTime.Time); - - // time should be further then last fixed step in update - Assert.Less(m_LocalTimePreviousFixedUpdate.FixedTime, localTime.Time); - - // we should be in same or further tick then fixed update - Assert.LessOrEqual(m_LocalTimePreviousFixedUpdate.Tick, localTime.Tick); - - // fixed update should result in same amounts of tick as network time - if (m_TickOffset == -1) - { - m_TickOffset = serverTime.Tick - m_LastFixedUpdateTick; - } - else - { - // offset of 1 is ok, this happens due to different tick duration offsets - Assert.LessOrEqual(Mathf.Abs(serverTime.Tick - m_TickOffset - m_LastFixedUpdateTick), 1); - } - - m_LocalTimePreviousUpdate = localTime; - m_ServerTimePreviousUpdate = serverTime; - } - - private void FixedUpdate() - { - m_LocalTimePreviousFixedUpdate = NetworkManager.Singleton.LocalTime; - - Assert.AreEqual(Time.fixedDeltaTime, m_LocalTimePreviousFixedUpdate.FixedDeltaTime); - Assert.AreEqual((float)NetworkManager.Singleton.LocalTime.Time, (float)NetworkManager.Singleton.ServerTime.Time, null, FloatComparer.s_ComparerWithDefaultTolerance); - m_LastFixedUpdateTick++; - } - - public bool IsTestFinished => m_UpdatePasses >= Passes; - } - - internal class PlayerLoopTimeTestComponent : MonoBehaviour, IMonoBehaviourTest - { - public const int Passes = 100; - - private int m_UpdatePasses = 0; - - private NetworkTime m_LocalTimePreviousUpdate; - private NetworkTime m_ServerTimePreviousUpdate; - private NetworkTime m_LocalTimePreviousFixedUpdate; - - private void Update() - { - // This must run first else it wont run if there is an exception - m_UpdatePasses++; - - NetworkTime localTime = NetworkManager.Singleton.LocalTime; - NetworkTime serverTime = NetworkManager.Singleton.ServerTime; - - // time should have advanced on the host/server - Assert.Less(m_LocalTimePreviousUpdate.Time, localTime.Time); - Assert.Less(m_ServerTimePreviousUpdate.Time, serverTime.Time); - - // time should be further then last fixed step in update - Assert.Less(m_LocalTimePreviousFixedUpdate.FixedTime, localTime.Time); - - // we should be in same or further tick then fixed update - Assert.LessOrEqual(m_LocalTimePreviousFixedUpdate.Tick, localTime.Tick); - - m_LocalTimePreviousUpdate = localTime; - m_ServerTimePreviousUpdate = serverTime; - } - - private void FixedUpdate() - { - m_LocalTimePreviousFixedUpdate = NetworkManager.Singleton.LocalTime; - } - - public bool IsTestFinished => m_UpdatePasses >= Passes; - } - -} diff --git a/Tests/Runtime/Timing/NetworkTimeSystemTests.cs.meta b/Tests/Runtime/Timing/NetworkTimeSystemTests.cs.meta deleted file mode 100644 index d87b284..0000000 --- a/Tests/Runtime/Timing/NetworkTimeSystemTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c9dcad9faf35434d8b997e769ece4d9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Timing/TimeInitializationTest.cs b/Tests/Runtime/Timing/TimeInitializationTest.cs deleted file mode 100644 index 5d8f39c..0000000 --- a/Tests/Runtime/Timing/TimeInitializationTest.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Tests that the time and tick system are initialized properly - /// - internal class TimeInitializationTest - { - private int m_ClientTickCounter; - private int m_ConnectedTick; - private NetworkManager m_Client; - - [UnityTest] - public IEnumerator TestClientTimeInitializationOnConnect([Values(0, 1f)] float serverStartDelay, [Values(0, 1f)] float clientStartDelay, [Values(true, false)] bool isHost) - { - // Create multiple NetworkManager instances - if (!NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients, 30)) - { - Debug.LogError("Failed to create instances"); - Assert.Fail("Failed to create instances"); - } - - yield return new WaitForSeconds(serverStartDelay); - NetcodeIntegrationTestHelpers.Start(false, server, new NetworkManager[] { }); // passing no clients on purpose to start them manually later - - // 0 ticks should have passed - var serverTick = server.NetworkTickSystem.ServerTime.Tick; - Assert.AreEqual(0, serverTick); - - // server time should be 0 - Assert.AreEqual(0, server.NetworkTickSystem.ServerTime.Time); - - // wait until at least more than 2 server ticks have passed - // Note: Waiting for more than 2 ticks on the server is due - // to the time system applying buffering to the received time - // in NetworkTimeSystem.Sync - yield return new WaitUntil(() => server.NetworkTickSystem.ServerTime.Tick > 2); - - var serverTimePassed = server.NetworkTickSystem.ServerTime.Time; - var expectedServerTickCount = Mathf.FloorToInt((float)(serverTimePassed * 30)); - - var ticksPassed = server.NetworkTickSystem.ServerTime.Tick - serverTick; - Assert.AreEqual(expectedServerTickCount, ticksPassed); - - yield return new WaitForSeconds(clientStartDelay); - - Assert.AreEqual(1, clients.Length); - m_Client = clients[0]; - - Assert.Null(m_Client.NetworkTickSystem); - - m_Client.OnClientConnectedCallback += ClientOnOnClientConnectedCallback; - - var clientStartRealTime = Time.time; - - m_Client.StartClient(); - NetcodeIntegrationTestHelpers.RegisterHandlers(clients[0]); - - m_Client.NetworkTickSystem.Tick += NetworkTickSystemOnTick; - m_ClientTickCounter = 0; - - // Wait for connection on client side - yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients); - - var clientStartRealTimeDuration = Time.time - clientStartRealTime; - var clientStartRealTickDuration = Mathf.FloorToInt(clientStartRealTimeDuration * 30); - - // check tick is initialized with server value - Assert.AreNotEqual(0, m_ConnectedTick); - - Assert.True(m_ClientTickCounter <= clientStartRealTickDuration); - - yield return null; - } - - private void NetworkTickSystemOnTick() - { - //Debug.Log(m_Client.NetworkTickSystem.ServerTime.Tick); - m_ClientTickCounter++; - } - - private void ClientOnOnClientConnectedCallback(ulong id) - { - // client connected to server - m_ConnectedTick = m_Client.NetworkTickSystem.ServerTime.Tick; - //Debug.Log($"Connected tick: {m_ConnectedTick}"); - } - - [UnityTearDown] - public virtual IEnumerator Teardown() - { - NetcodeIntegrationTestHelpers.Destroy(); - yield return null; - } - } -} diff --git a/Tests/Runtime/Timing/TimeInitializationTest.cs.meta b/Tests/Runtime/Timing/TimeInitializationTest.cs.meta deleted file mode 100644 index f5ab60f..0000000 --- a/Tests/Runtime/Timing/TimeInitializationTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8d1a3e8bb2e1d204abc82173fddc8977 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Timing/TimeIntegrationTest.cs b/Tests/Runtime/Timing/TimeIntegrationTest.cs deleted file mode 100644 index f6f8147..0000000 --- a/Tests/Runtime/Timing/TimeIntegrationTest.cs +++ /dev/null @@ -1,203 +0,0 @@ -#if !MULTIPLAYER_TOOLS -using System; -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - -namespace Unity.Netcode.RuntimeTests -{ - /// - /// Tests the times of two clients connecting to a server using the SIPTransport (returns 50ms RTT but has no latency simulation) - /// - internal class TimeIntegrationTest : NetcodeIntegrationTest - { - private const double k_AdditionalTimeTolerance = 0.3333d; // magic number and in theory not needed but without this mac os test fail in Yamato because it looks like we get random framerate drops during unit test. - - private NetworkTimeState m_ServerState; - private NetworkTimeState m_Client1State; - private NetworkTimeState m_Client2State; - - protected override int NumberOfClients => 2; - - protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() - { - return NetworkManagerInstatiationMode.DoNotCreate; - } - - private void UpdateTimeStates() - { - m_ServerState = new NetworkTimeState(m_ServerNetworkManager); - m_Client1State = new NetworkTimeState(m_ClientNetworkManagers[0]); - m_Client2State = new NetworkTimeState(m_ClientNetworkManagers[1]); - } - - [UnityTest] - [TestCase(60, 30u, ExpectedResult = null)] - [TestCase(30, 30u, ExpectedResult = null)] - [TestCase(40, 30u, ExpectedResult = null)] - [TestCase(10, 30u, ExpectedResult = null)] - [TestCase(60, 60u, ExpectedResult = null)] - [TestCase(60, 10u, ExpectedResult = null)] - public IEnumerator TestTimeIntegrationTest(int targetFrameRate, uint tickRate) - { - yield return StartSomeClientsAndServerWithPlayersCustom(true, NumberOfClients, targetFrameRate, tickRate); - - var additionalTimeTolerance = k_AdditionalTimeTolerance; - // Mac can dip down below 10fps when set at a 10fps range (i.e. known to hit as low as 8.85 fps) - // With the really low frame rate, add some additional time tolerance - if (targetFrameRate == 10) - { - additionalTimeTolerance += 0.0333333333333f; - } - - double frameInterval = 1d / targetFrameRate; - double tickInterval = 1d / tickRate; - - var server = m_ServerNetworkManager; - var firstClient = m_ClientNetworkManagers[0]; - var secondClient = m_ClientNetworkManagers[1]; - - // increase the buffer time of client 2 // the values for client 1 are 0.0333/0.0333 here - secondClient.NetworkTimeSystem.LocalBufferSec = 0.2; - secondClient.NetworkTimeSystem.ServerBufferSec = 0.1; - - UpdateTimeStates(); - - // wait for a few ticks to pass - for (int i = 0; i < 4; i++) - { - yield return s_DefaultWaitForTick; - } - - var framesToRun = 3d / frameInterval; - - var waitForNextFrame = new WaitForFixedUpdate(); - - for (int i = 0; i < framesToRun; i++) - { - // Assure we wait for 1 frame to get the current frame time to check for low frame rates relative to expected frame rates - yield return waitForNextFrame; - - // Adjust the time tolerance based on slower than expected FPS - var currentFPS = 1.0f / Time.deltaTime; - var fpsAdjustment = 1.0f; - var currentAdjustment = additionalTimeTolerance; - if (currentFPS < targetFrameRate) - { - // Get the % slower and increase the time tolerance based on that % - var fpsDelta = targetFrameRate - currentFPS; - fpsAdjustment = 1.0f / fpsDelta; - currentAdjustment += additionalTimeTolerance * fpsAdjustment; - } - - UpdateTimeStates(); - - // compares whether client times have the correct offset to server - m_ServerState.AssertCheckDifference(m_Client1State, tickInterval, tickInterval, tickInterval * 2 + frameInterval * 2 + currentAdjustment); - m_ServerState.AssertCheckDifference(m_Client2State, 0.2, 0.1, tickInterval * 2 + frameInterval * 2 + currentAdjustment); - - // compares the two client times, only difference should be based on buffering. - m_Client1State.AssertCheckDifference(m_Client2State, 0.2 - tickInterval, (0.1 - tickInterval), tickInterval * 2 + frameInterval * 2 + currentAdjustment); - } - } - - protected override IEnumerator OnTearDown() - { - // Always "shutdown in a tear-down" otherwise you can cause all proceeding tests to fail - ShutdownAndCleanUp(); - yield return base.OnTearDown(); - } - - // This is from NetcodeIntegrationTest but we need a custom version of this to modifiy the config - private IEnumerator StartSomeClientsAndServerWithPlayersCustom(bool useHost, int nbClients, int targetFrameRate, uint tickRate) - { - // Create multiple NetworkManager instances - if (!NetcodeIntegrationTestHelpers.Create(nbClients, out NetworkManager server, out NetworkManager[] clients, targetFrameRate)) - { - Debug.LogError("Failed to create instances"); - Assert.Fail("Failed to create instances"); - } - - m_ClientNetworkManagers = clients; - m_ServerNetworkManager = server; - - // Create playerPrefab - m_PlayerPrefab = new GameObject("Player"); - NetworkObject networkObject = m_PlayerPrefab.AddComponent(); - - /* - * Normally we would only allow player prefabs to be set to a prefab. Not runtime created objects. - * In order to prevent having a Resource folder full of a TON of prefabs that we have to maintain, - * NetcodeIntegrationTestHelpers has a helper function that lets you mark a runtime created object to be - * treated as a prefab by the Netcode. That's how we can get away with creating the player prefab - * at runtime without it being treated as a SceneObject or causing other conflicts with the Netcode. - */ - // Make it a prefab - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject); - - // Set the player prefab - server.NetworkConfig.PlayerPrefab = m_PlayerPrefab; - - for (int i = 0; i < clients.Length; i++) - { - clients[i].NetworkConfig.PlayerPrefab = m_PlayerPrefab; - clients[i].NetworkConfig.TickRate = tickRate; - } - - server.NetworkConfig.TickRate = tickRate; - - // Start the instances - if (!NetcodeIntegrationTestHelpers.Start(useHost, server, clients)) - { - Debug.LogError("Failed to start instances"); - Assert.Fail("Failed to start instances"); - } - - // Wait for connection on client and server side - yield return WaitForClientsConnectedOrTimeOut(); - AssertOnTimeout($"Timed-out waiting for all clients to connect!"); - } - - private readonly struct NetworkTimeState : IEquatable - { - public NetworkTime LocalTime { get; } - public NetworkTime ServerTime { get; } - - public NetworkTimeState(NetworkManager manager) - { - LocalTime = manager.NetworkTickSystem.LocalTime; - ServerTime = manager.NetworkTickSystem.ServerTime; - } - - public void AssertCheckDifference(NetworkTimeState clientState, double localBufferDifference, double serverBufferDifference, double tolerance) - { - var difLocalAbs = Math.Abs(clientState.LocalTime.Time - LocalTime.Time - localBufferDifference); - var difServerAbs = Math.Abs(ServerTime.Time - clientState.ServerTime.Time - serverBufferDifference); - - Assert.True(difLocalAbs < tolerance, $"localtime difference: {difLocalAbs} bigger than tolerance: {tolerance}"); - Assert.True(difServerAbs < tolerance, $"servertime difference: {difServerAbs} bigger than tolerance: {tolerance}"); - } - - public bool Equals(NetworkTimeState other) - { - return LocalTime.Time.Equals(other.LocalTime.Time) && ServerTime.Time.Equals(other.ServerTime.Time); - } - - public override bool Equals(object obj) - { - return obj is NetworkTimeState other && Equals(other); - } - - public override int GetHashCode() - { - unchecked - { - return (LocalTime.Time.GetHashCode() * 397) ^ ServerTime.Time.GetHashCode(); - } - } - } - } -} -#endif diff --git a/Tests/Runtime/Timing/TimeIntegrationTest.cs.meta b/Tests/Runtime/Timing/TimeIntegrationTest.cs.meta deleted file mode 100644 index 4cf2ed5..0000000 --- a/Tests/Runtime/Timing/TimeIntegrationTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 71180f84c488966489fe44d57bf085d1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/TransformInterpolationTests.cs b/Tests/Runtime/TransformInterpolationTests.cs deleted file mode 100644 index 4e0cea8..0000000 --- a/Tests/Runtime/TransformInterpolationTests.cs +++ /dev/null @@ -1,236 +0,0 @@ -#if !MULTIPLAYER_TOOLS -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Components; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using UnityEngine.TestTools; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class TransformInterpolationObject : NetworkTransform - { - public static bool TestComplete = false; - // Set the minimum threshold which we will use as our margin of error -#if UNITY_EDITOR - public const float MinThreshold = 0.005f; -#else - // Add additional room for error on console tests - public const float MinThreshold = 0.009999f; -#endif - - private const int k_TargetLocalSpaceToggles = 10; - - public bool CheckPosition; - public bool IsMoving; - public bool IsFixed; - - private float m_FrameRateFractional; - private bool m_CurrentLocalSpace; - - private int m_LocalSpaceToggles; - private int m_LastFrameCount; - - public bool ReachedTargetLocalSpaceTransitionCount() - { - TestComplete = m_LocalSpaceToggles >= k_TargetLocalSpaceToggles; - return TestComplete; - } - - protected override void OnInitialize(ref NetworkTransformState replicatedState) - { - m_LocalSpaceToggles = 0; - m_FrameRateFractional = 1.0f / Application.targetFrameRate; - PositionThreshold = MinThreshold; - SetMaxInterpolationBound(1.0f); - base.OnInitialize(ref replicatedState); - } - - private int m_StartFrameCount; - - public void StartMoving() - { - m_StartFrameCount = Time.frameCount; - IsMoving = true; - } - - public void StopMoving() - { - IsMoving = false; - } - - private const int k_MaxThresholdFailures = 4; - private int m_ExceededThresholdCount; - - public override void OnUpdate() - { - base.OnUpdate(); - - - // Check the position of the nested object on the client - if (CheckPosition) - { - if (transform.position.y < -MinThreshold || transform.position.y > Application.targetFrameRate + MinThreshold) - { - // Temporary work around for this test. - // Really, this test needs to be completely re-written. - m_ExceededThresholdCount++; - // If we haven't corrected ourselves within the maximum number of updates then throw an error. - if (m_ExceededThresholdCount > k_MaxThresholdFailures) - { - Debug.LogError($"Interpolation failure. transform.position.y is {transform.position.y}. Should be between 0.0 and 100.0. Current threshold is [+/- {MinThreshold}]."); - } - } - else - { - // If corrected, then reset our count - m_ExceededThresholdCount = 0; - } - } - } - - private void Update() - { - base.OnUpdate(); - - if (!IsSpawned || !CanCommitToTransform || TestComplete) - { - return; - } - - - // Move the nested object on the server - if (IsMoving) - { - Assert.True(CanCommitToTransform, $"Using non-authority instance to update transform!"); - - if (m_LastFrameCount == Time.frameCount) - { - Debug.Log($"Detected duplicate frame update count {Time.frameCount}. Ignoring this update."); - return; - } - - m_LastFrameCount = Time.frameCount; - - // Leaving this here for reference. - // If a system is running at a slower frame rate than expected, then the below code could toggle - // the local to world space value at a higher frequency which might not provide enough updates to - // handle interpolating between the transitions. - //var y = Time.realtimeSinceStartup % 10.0f; - //// change the space between local and global every second - //GetComponent().InLocalSpace = ((int)y % 2 == 0); - - // Reduce the total frame count down to the frame rate - var y = (Time.frameCount - m_StartFrameCount) % Application.targetFrameRate; - - // change the space between local and global every time we hit the expected number of frames - // (or every second if running at the target frame rate) - InLocalSpace = y == 0 ? !InLocalSpace : InLocalSpace; - - if (m_CurrentLocalSpace != InLocalSpace) - { - m_LocalSpaceToggles++; - m_CurrentLocalSpace = InLocalSpace; - } - - transform.position = new Vector3(0.0f, (y * m_FrameRateFractional), 0.0f); - } - - // On the server, make sure to keep the parent object at a fixed position - if (IsFixed) - { - Assert.True(CanCommitToTransform, $"Using non-authority instance to update transform!"); - transform.position = new Vector3(1000.0f, 1000.0f, 1000.0f); - } - } - } - - internal class TransformInterpolationTests : NetcodeIntegrationTest - { - protected override int NumberOfClients => 1; - - private GameObject m_PrefabToSpawn; - - private NetworkObject m_SpawnedAsNetworkObject; - private NetworkObject m_SpawnedObjectOnClient; - - private NetworkObject m_BaseAsNetworkObject; - private NetworkObject m_BaseOnClient; - - - protected override void OnServerAndClientsCreated() - { - m_PrefabToSpawn = CreateNetworkObjectPrefab("InterpTestObject"); - var networkTransform = m_PrefabToSpawn.AddComponent(); - } - - private IEnumerator RefreshNetworkObjects() - { - var clientId = m_ClientNetworkManagers[0].LocalClientId; - yield return WaitForConditionOrTimeOut(() => s_GlobalNetworkObjects.ContainsKey(clientId) && - s_GlobalNetworkObjects[clientId].ContainsKey(m_BaseAsNetworkObject.NetworkObjectId) && - s_GlobalNetworkObjects[clientId].ContainsKey(m_SpawnedAsNetworkObject.NetworkObjectId)); - - Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client side {nameof(NetworkObject)} ID of {m_SpawnedAsNetworkObject.NetworkObjectId}"); - - m_BaseOnClient = s_GlobalNetworkObjects[clientId][m_BaseAsNetworkObject.NetworkObjectId]; - // make sure the objects are set with the right network manager - m_BaseOnClient.NetworkManagerOwner = m_ClientNetworkManagers[0]; - - m_SpawnedObjectOnClient = s_GlobalNetworkObjects[clientId][m_SpawnedAsNetworkObject.NetworkObjectId]; - // make sure the objects are set with the right network manager - m_SpawnedObjectOnClient.NetworkManagerOwner = m_ClientNetworkManagers[0]; - } - - [UnityTest] - public IEnumerator TransformInterpolationTest() - { - TransformInterpolationObject.TestComplete = false; - // create an object - var spawnedObject = Object.Instantiate(m_PrefabToSpawn); - var baseObject = Object.Instantiate(m_PrefabToSpawn); - baseObject.GetComponent().NetworkManagerOwner = m_ServerNetworkManager; - baseObject.GetComponent().Spawn(); - - m_SpawnedAsNetworkObject = spawnedObject.GetComponent(); - m_SpawnedAsNetworkObject.NetworkManagerOwner = m_ServerNetworkManager; - - m_BaseAsNetworkObject = baseObject.GetComponent(); - m_BaseAsNetworkObject.NetworkManagerOwner = m_ServerNetworkManager; - - m_SpawnedAsNetworkObject.TrySetParent(baseObject); - - m_SpawnedAsNetworkObject.Spawn(); - - yield return RefreshNetworkObjects(); - - m_SpawnedAsNetworkObject.TrySetParent(baseObject); - var spawnedObjectNetworkTransform = spawnedObject.GetComponent(); - baseObject.GetComponent().IsFixed = true; - spawnedObject.GetComponent().StartMoving(); - - const float maxPlacementError = 0.01f; - - // Wait for the base object to place itself on both instances - while (m_BaseOnClient.transform.position.y < 1000 - maxPlacementError || - m_BaseOnClient.transform.position.y > 1000 + maxPlacementError || - baseObject.transform.position.y < 1000 - maxPlacementError || - baseObject.transform.position.y > 1000 + maxPlacementError) - { - yield return new WaitForSeconds(0.01f); - } - - m_SpawnedObjectOnClient.GetComponent().CheckPosition = true; - - // Test that interpolation works correctly for ~10 seconds or 10 local to world space transitions while moving - // Increasing this duration gives you the opportunity to go check in the Editor how the objects are setup - // and how they move - var timeOutHelper = new TimeoutFrameCountHelper(10); - yield return WaitForConditionOrTimeOut(spawnedObjectNetworkTransform.ReachedTargetLocalSpaceTransitionCount, timeOutHelper); - VerboseDebug($"[TransformInterpolationTest] Wait condition reached or timed out. Frame Count ({timeOutHelper.GetFrameCount()}) | Time Elapsed ({timeOutHelper.GetTimeElapsed()})"); - AssertOnTimeout($"Failed to reach desired local to world space transitions in the given time!", timeOutHelper); - } - } -} -#endif diff --git a/Tests/Runtime/TransformInterpolationTests.cs.meta b/Tests/Runtime/TransformInterpolationTests.cs.meta deleted file mode 100644 index 79d5dfa..0000000 --- a/Tests/Runtime/TransformInterpolationTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 99e1c086232df436498da7c180b59898 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports.meta b/Tests/Runtime/Transports.meta deleted file mode 100644 index 652b01e..0000000 --- a/Tests/Runtime/Transports.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: be6919760502fc9419376258fd62ec0e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports/DummyTransport.cs b/Tests/Runtime/Transports/DummyTransport.cs deleted file mode 100644 index 08d873f..0000000 --- a/Tests/Runtime/Transports/DummyTransport.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; - - -namespace Unity.Netcode.RuntimeTests -{ - internal class DummyTransport : TestingNetworkTransport - { - public override ulong ServerClientId { get; } = 0; - public override void Send(ulong clientId, ArraySegment payload, NetworkDelivery networkDelivery) - { - } - - public override NetworkEvent PollEvent(out ulong clientId, out ArraySegment payload, out float receiveTime) - { - clientId = 0; - payload = new ArraySegment(); - receiveTime = 0; - return NetworkEvent.Nothing; - } - - public override bool StartClient() - { - return true; - } - - public override bool StartServer() - { - return true; - } - - public override void DisconnectRemoteClient(ulong clientId) - { - } - - public override void DisconnectLocalClient() - { - } - - public override ulong GetCurrentRtt(ulong clientId) - { - return 0; - } - - public override void Shutdown() - { - } - - public override void Initialize(NetworkManager networkManager = null) - { - } - } -} diff --git a/Tests/Runtime/Transports/DummyTransport.cs.meta b/Tests/Runtime/Transports/DummyTransport.cs.meta deleted file mode 100644 index 5a9c34f..0000000 --- a/Tests/Runtime/Transports/DummyTransport.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 976ca592c7fa4bcb854203dfbadc0ad9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports/UnityTransportConnectionTests.cs b/Tests/Runtime/Transports/UnityTransportConnectionTests.cs deleted file mode 100644 index ac4c089..0000000 --- a/Tests/Runtime/Transports/UnityTransportConnectionTests.cs +++ /dev/null @@ -1,399 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using UnityEngine; -using UnityEngine.TestTools; -using static Unity.Netcode.RuntimeTests.UnityTransportTestHelpers; - -namespace Unity.Netcode.RuntimeTests -{ - internal class UnityTransportConnectionTests - { - // For tests using multiple clients. - private const int k_NumClients = 5; - private UnityTransport m_Server; - private UnityTransport[] m_Clients = new UnityTransport[k_NumClients]; - private List m_ServerEvents; - private List[] m_ClientsEvents = new List[k_NumClients]; - - [UnityTearDown] - public IEnumerator Cleanup() - { - if (m_Server) - { - m_Server.Shutdown(); - UnityEngine.Object.DestroyImmediate(m_Server); - } - - foreach (var transport in m_Clients) - { - if (transport) - { - transport.Shutdown(); - UnityEngine.Object.DestroyImmediate(transport); - } - } - - foreach (var transportEvents in m_ClientsEvents) - { - transportEvents?.Clear(); - } - - yield return null; - } - - // Check that invalid endpoint addresses are detected and return false if detected - [Test] - public void DetectInvalidEndpoint() - { - using var netcodeLogAssert = new NetcodeLogAssert(true); - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - m_Server.ConnectionData.Address = "Fubar"; - m_Server.ConnectionData.ServerListenAddress = "Fubar"; - m_Clients[0].ConnectionData.Address = "MoreFubar"; - Assert.False(m_Server.StartServer(), "Server failed to detect invalid endpoint!"); - Assert.False(m_Clients[0].StartClient(), "Client failed to detect invalid endpoint!"); - netcodeLogAssert.LogWasReceived(LogType.Error, $"Network listen address ({m_Server.ConnectionData.Address}) is Invalid!"); - netcodeLogAssert.LogWasReceived(LogType.Error, $"Target server network address ({m_Clients[0].ConnectionData.Address}) is Invalid!"); - } - - // Check connection with a single client. - [UnityTest] - public IEnumerator ConnectSingleClient() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - // Check we've received Connect event on server too. - Assert.AreEqual(1, m_ServerEvents.Count); - Assert.AreEqual(NetworkEvent.Connect, m_ServerEvents[0].Type); - - yield return null; - } - - // Check connection with multiple clients. - [UnityTest] - public IEnumerator ConnectMultipleClients() - { - InitializeTransport(out m_Server, out m_ServerEvents); - m_Server.StartServer(); - - for (int i = 0; i < k_NumClients; i++) - { - InitializeTransport(out m_Clients[i], out m_ClientsEvents[i]); - m_Clients[i].StartClient(); - } - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[k_NumClients - 1]); - - // Check that every client received a Connect event. - Assert.True(m_ClientsEvents.All(evs => evs.Count == 1)); - Assert.True(m_ClientsEvents.All(evs => evs[0].Type == NetworkEvent.Connect)); - - // Check we've received Connect events on server too. - Assert.AreEqual(k_NumClients, m_ServerEvents.Count); - Assert.True(m_ServerEvents.All(ev => ev.Type == NetworkEvent.Connect)); - - yield return null; - } - - // Check server disconnection with a single client. - [UnityTest] - public IEnumerator ServerDisconnectSingleClient() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ClientsEvents[0]); - - yield return null; - } - - // Check server disconnection with multiple clients. - [UnityTest] - public IEnumerator ServerDisconnectMultipleClients() - { - InitializeTransport(out m_Server, out m_ServerEvents); - m_Server.StartServer(); - - for (int i = 0; i < k_NumClients; i++) - { - InitializeTransport(out m_Clients[i], out m_ClientsEvents[i]); - m_Clients[i].StartClient(); - } - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[k_NumClients - 1]); - - // Disconnect a single client. - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - // Need to manually wait since we don't know which client will get the Disconnect. - yield return new WaitForSeconds(MaxNetworkEventWaitTime); - - // Check that we received a Disconnect event on only one client. - Assert.AreEqual(1, m_ClientsEvents.Count(evs => evs.Count == 2 && evs[1].Type == NetworkEvent.Disconnect)); - - // Disconnect all the other clients. - for (int i = 1; i < k_NumClients; i++) - { - m_Server.DisconnectRemoteClient(m_ServerEvents[i].ClientID); - } - - // Need to manually wait since we don't know which client got the Disconnect. - yield return new WaitForSeconds(MaxNetworkEventWaitTime); - - // Check that all clients got a Disconnect event. - Assert.True(m_ClientsEvents.All(evs => evs.Count == 2)); - Assert.True(m_ClientsEvents.All(evs => evs[1].Type == NetworkEvent.Disconnect)); - - yield return null; - } - - // Check client disconnection from a single client. - [UnityTest] - public IEnumerator ClientDisconnectSingleClient() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - m_Clients[0].DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents); - } - - // Check client disconnection with multiple clients. - [UnityTest] - public IEnumerator ClientDisconnectMultipleClients() - { - InitializeTransport(out m_Server, out m_ServerEvents); - m_Server.StartServer(); - - for (int i = 0; i < k_NumClients; i++) - { - InitializeTransport(out m_Clients[i], out m_ClientsEvents[i]); - m_Clients[i].StartClient(); - } - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[k_NumClients - 1]); - - // Disconnect a single client. - m_Clients[0].DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents); - - // Disconnect all the other clients. - for (int i = 1; i < k_NumClients; i++) - { - m_Clients[i].DisconnectLocalClient(); - } - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents, 5); - - // Check that we got the correct number of Disconnect events on the server. - Assert.AreEqual(k_NumClients * 2, m_ServerEvents.Count); - Assert.AreEqual(k_NumClients, m_ServerEvents.Count(e => e.Type == NetworkEvent.Disconnect)); - - yield return null; - } - - // Check that server re-disconnects are no-ops. - [UnityTest] - public IEnumerator RepeatedServerDisconnectsNoop() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ClientsEvents[0]); - - var previousServerEventsCount = m_ServerEvents.Count; - var previousClientEventsCount = m_ClientsEvents[0].Count; - - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - // Need to wait manually since no event should be generated. - yield return new WaitForSeconds(MaxNetworkEventWaitTime); - - // Check we haven't received anything else on the client or server. - Assert.AreEqual(m_ServerEvents.Count, previousServerEventsCount); - Assert.AreEqual(m_ClientsEvents[0].Count, previousClientEventsCount); - - yield return null; - } - - // Check that client re-disconnects are no-ops. - [UnityTest] - public IEnumerator RepeatedClientDisconnectsNoop() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - m_Clients[0].DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents); - - var previousServerEventsCount = m_ServerEvents.Count; - var previousClientEventsCount = m_ClientsEvents[0].Count; - - m_Clients[0].DisconnectLocalClient(); - - // Need to wait manually since no event should be generated. - yield return new WaitForSeconds(MaxNetworkEventWaitTime); - - // Check we haven't received anything else on the client or server. - Assert.AreEqual(m_ServerEvents.Count, previousServerEventsCount); - Assert.AreEqual(m_ClientsEvents[0].Count, previousClientEventsCount); - - yield return null; - } - - // Check connection with different server/listen addresses. - [UnityTest] - public IEnumerator DifferentServerAndListenAddresses() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.SetConnectionData("127.0.0.1", 10042, "0.0.0.0"); - m_Clients[0].SetConnectionData("127.0.0.1", 10042); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - // Check we've received Connect event on server too. - Assert.AreEqual(1, m_ServerEvents.Count); - Assert.AreEqual(NetworkEvent.Connect, m_ServerEvents[0].Type); - - yield return null; - } - - // Check server disconnection with data in send queue. - [UnityTest] - public IEnumerator ServerDisconnectWithDataInQueue() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - // Wait for the client to connect before we disconnect the client - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - var data = new ArraySegment(new byte[] { 42 }); - m_Server.Send(m_ServerEvents[0].ClientID, data, NetworkDelivery.Unreliable); - - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ClientsEvents[0]); - - if (m_ClientsEvents[0].Count >= 3) - { - Assert.AreEqual(NetworkEvent.Disconnect, m_ClientsEvents[0][2].Type); - } - else - { - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ClientsEvents[0]); - } - } - - // Check client disconnection with data in send queue. - [UnityTest] - public IEnumerator ClientDisconnectWithDataInQueue() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - - m_Server.StartServer(); - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ServerEvents); - - var data = new ArraySegment(new byte[] { 42 }); - m_Clients[0].Send(m_Clients[0].ServerClientId, data, NetworkDelivery.Unreliable); - - m_Clients[0].DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - if (m_ServerEvents.Count >= 3) - { - Assert.AreEqual(NetworkEvent.Disconnect, m_ServerEvents[2].Type); - } - else - { - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents); - } - } - - // Check that a server can disconnect a client after another client has disconnected. - [UnityTest] - public IEnumerator ServerDisconnectAfterClientDisconnect() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); - InitializeTransport(out m_Clients[1], out m_ClientsEvents[1]); - - m_Server.StartServer(); - - m_Clients[0].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); - - m_Clients[1].StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[1]); - - m_Clients[0].DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ServerEvents); - - // Pick the client ID of the still connected client. - var clientId = m_ServerEvents[0].ClientID; - if (m_ServerEvents[2].ClientID == clientId) - { - clientId = m_ServerEvents[1].ClientID; - } - - m_Server.DisconnectRemoteClient(clientId); - - yield return WaitForNetworkEvent(NetworkEvent.Disconnect, m_ClientsEvents[1]); - - yield return null; - } - } -} diff --git a/Tests/Runtime/Transports/UnityTransportConnectionTests.cs.meta b/Tests/Runtime/Transports/UnityTransportConnectionTests.cs.meta deleted file mode 100644 index fbdf1b9..0000000 --- a/Tests/Runtime/Transports/UnityTransportConnectionTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0a6b90810a6304cd98c615c9828888a5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports/UnityTransportDriverClient.cs b/Tests/Runtime/Transports/UnityTransportDriverClient.cs deleted file mode 100644 index ef8ca26..0000000 --- a/Tests/Runtime/Transports/UnityTransportDriverClient.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Collections; -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using Unity.Networking.Transport; -using Unity.Networking.Transport.Utilities; -using UnityEngine; -using static Unity.Netcode.RuntimeTests.UnityTransportTestHelpers; -using UTPNetworkEvent = Unity.Networking.Transport.NetworkEvent; - -namespace Unity.Netcode.RuntimeTests -{ - // Thin wrapper around a UTP NetworkDriver that can act as a client to a UnityTransport server. - // In particular that means the pipelines are set up the same way as in UnityTransport. - // - // The only reason it's defined as a MonoBehaviour is that OnDestroy is the only reliable way - // to get the driver's Dispose method called from a UnityTest. Making it disposable would be - // the preferred solution, but that doesn't always mesh well with coroutines. - internal class UnityTransportDriverClient : MonoBehaviour - { - private NetworkDriver m_Driver; - public NetworkDriver Driver => m_Driver; - - private NetworkConnection m_Connection; - - private NetworkPipeline m_UnreliableSequencedPipeline; - private NetworkPipeline m_ReliableSequencedPipeline; - private NetworkPipeline m_ReliableSequencedFragmentedPipeline; - - public NetworkPipeline UnreliableSequencedPipeline => m_UnreliableSequencedPipeline; - public NetworkPipeline ReliableSequencedPipeline => m_ReliableSequencedPipeline; - public NetworkPipeline ReliableSequencedFragmentedPipeline => m_ReliableSequencedFragmentedPipeline; - - private NetworkPipeline m_LastEventPipeline; - public NetworkPipeline LastEventPipeline => m_LastEventPipeline; - - private void Awake() - { - var maxCap = UnityTransport.InitialMaxPayloadSize + 128; - - var settings = new NetworkSettings(); - settings.WithFragmentationStageParameters(payloadCapacity: maxCap); - - var fragParams = new FragmentationUtility.Parameters() { PayloadCapacity = maxCap }; - - m_Driver = NetworkDriver.Create(settings); - - m_UnreliableSequencedPipeline = m_Driver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); - m_ReliableSequencedPipeline = m_Driver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); - m_ReliableSequencedFragmentedPipeline = m_Driver.CreatePipeline(typeof(FragmentationPipelineStage), typeof(ReliableSequencedPipelineStage)); - } - - private void Update() - { - m_Driver.ScheduleUpdate().Complete(); - } - - private void OnDestroy() - { - if (m_Driver.IsCreated) - { - m_Driver.Dispose(); - } - } - - public void Connect() - { -#if UTP_TRANSPORT_2_0_ABOVE - var endpoint = NetworkEndpoint.LoopbackIpv4; -#else - var endpoint = NetworkEndPoint.LoopbackIpv4; -#endif - endpoint.Port = 7777; - - m_Connection = m_Driver.Connect(endpoint); - } - - // Wait for the given event to be generated by the client's driver. - public IEnumerator WaitForNetworkEvent(UTPNetworkEvent.Type type) - { - float startTime = Time.realtimeSinceStartup; - - while (Time.realtimeSinceStartup - startTime < MaxNetworkEventWaitTime) - { - UTPNetworkEvent.Type eventType = m_Driver.PopEvent(out _, out _, out m_LastEventPipeline); - if (eventType != UTPNetworkEvent.Type.Empty) - { - Assert.AreEqual(type, eventType); - yield break; - } - - yield return null; - } - - Assert.Fail("Timed out while waiting for network event."); - } - } -} diff --git a/Tests/Runtime/Transports/UnityTransportDriverClient.cs.meta b/Tests/Runtime/Transports/UnityTransportDriverClient.cs.meta deleted file mode 100644 index e3a021a..0000000 --- a/Tests/Runtime/Transports/UnityTransportDriverClient.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a087bb407f16c402dbc67a2ab9386eab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports/UnityTransportTestHelpers.cs b/Tests/Runtime/Transports/UnityTransportTestHelpers.cs deleted file mode 100644 index 62ae2b5..0000000 --- a/Tests/Runtime/Transports/UnityTransportTestHelpers.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using Unity.Networking.Transport; -using UnityEngine; - -namespace Unity.Netcode.RuntimeTests -{ - internal static class UnityTransportTestHelpers - { - // Half a second might seem like a very long time to wait for a network event, but in CI - // many of the machines are underpowered (e.g. old Android devices or Macs) and there are - // sometimes very high lag spikes. PS4 and Switch are particularly sensitive in this regard - // so we allow even more time for these platforms. - public const float MaxNetworkEventWaitTime = 0.5f; - - // Wait for an event to appear in the given event list (must be the very next event). - public static IEnumerator WaitForNetworkEvent(NetworkEvent type, List events, float timeout = MaxNetworkEventWaitTime) - { - int initialCount = events.Count; - float startTime = Time.realtimeSinceStartup; - - while (Time.realtimeSinceStartup - startTime < timeout) - { - if (events.Count > initialCount) - { - Assert.AreEqual(type, events[initialCount].Type); - yield break; - } - - yield return new WaitForSeconds(0.01f); - } - - Assert.Fail("Timed out while waiting for network event."); - } - - // Common code to initialize a UnityTransport that logs its events. - public static void InitializeTransport(out UnityTransport transport, out List events, - int maxPayloadSize = UnityTransport.InitialMaxPayloadSize, int maxSendQueueSize = 0, NetworkFamily family = NetworkFamily.Ipv4) - { - var logger = new TransportEventLogger(); - events = logger.Events; - - transport = new GameObject().AddComponent(); - - transport.OnTransportEvent += logger.HandleEvent; - transport.MaxPayloadSize = maxPayloadSize; - transport.MaxSendQueueSize = maxSendQueueSize; - - if (family == NetworkFamily.Ipv6) - { - transport.SetConnectionData("::1", 7777); - } - - transport.Initialize(); - } - - // Information about an event generated by a transport (basically just the parameters that - // are normally passed along to a TransportEventDelegate). - internal struct TransportEvent - { - public NetworkEvent Type; - public ulong ClientID; - public ArraySegment Data; - public float ReceiveTime; - } - // Utility class that logs events generated by a UnityTransport. Set it up by adding the - // HandleEvent method as an OnTransportEvent delegate of the transport. The list of events - // (in order in which they were generated) can be accessed through the Events property. - internal class TransportEventLogger - { - private readonly List m_Events = new List(); - public List Events => m_Events; - public void HandleEvent(NetworkEvent type, ulong clientID, ArraySegment data, float receiveTime) - { - // Copy the data since the backing array will be reused for future messages. - if (data != default(ArraySegment)) - { - var dataCopy = new byte[data.Count]; - Array.Copy(data.Array, data.Offset, dataCopy, 0, data.Count); - data = new ArraySegment(dataCopy); - } - m_Events.Add(new TransportEvent - { - Type = type, - ClientID = clientID, - Data = data, - ReceiveTime = receiveTime - }); - } - } - } -} diff --git a/Tests/Runtime/Transports/UnityTransportTestHelpers.cs.meta b/Tests/Runtime/Transports/UnityTransportTestHelpers.cs.meta deleted file mode 100644 index 2bef2ea..0000000 --- a/Tests/Runtime/Transports/UnityTransportTestHelpers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3af9d71bc7c414cebad947e6340de223 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/Transports/UnityTransportTests.cs b/Tests/Runtime/Transports/UnityTransportTests.cs deleted file mode 100644 index 4a14206..0000000 --- a/Tests/Runtime/Transports/UnityTransportTests.cs +++ /dev/null @@ -1,521 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Unity.Netcode.Transports.UTP; -using Unity.Networking.Transport; -using UnityEngine; -using UnityEngine.TestTools; -using static Unity.Netcode.RuntimeTests.UnityTransportTestHelpers; - -namespace Unity.Netcode.RuntimeTests -{ - internal class UnityTransportTests - { - // No need to test all reliable delivery methods since they all map to the same pipeline. - private static readonly NetworkDelivery[] k_DeliveryParameters = - { - NetworkDelivery.Unreliable, - NetworkDelivery.UnreliableSequenced, - NetworkDelivery.Reliable - }; - - private static readonly NetworkFamily[] k_NetworkFamiltyParameters = - { - NetworkFamily.Ipv4, -#if !(UNITY_SWITCH || UNITY_PS4 || UNITY_PS5) - // IPv6 is not supported on Switch, PS4, and PS5. - NetworkFamily.Ipv6 -#endif - }; - - private UnityTransport m_Server, m_Client1, m_Client2; - private List m_ServerEvents, m_Client1Events, m_Client2Events; - - [UnityTearDown] - public IEnumerator Cleanup() - { - if (m_Server) - { - m_Server.Shutdown(); - - // Need to destroy the GameObject (all assigned components will get destroyed too) - UnityEngine.Object.DestroyImmediate(m_Server.gameObject); - } - - if (m_Client1) - { - m_Client1.Shutdown(); - - // Need to destroy the GameObject (all assigned components will get destroyed too) - UnityEngine.Object.DestroyImmediate(m_Client1.gameObject); - } - - if (m_Client2) - { - m_Client2.Shutdown(); - - // Need to destroy the GameObject (all assigned components will get destroyed too) - UnityEngine.Object.DestroyImmediate(m_Client2.gameObject); - } - - m_ServerEvents?.Clear(); - m_Client1Events?.Clear(); - m_Client2Events?.Clear(); - - yield return null; - } - - // Check if can make a simple data exchange. - [UnityTest] - public IEnumerator PingPong( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - InitializeTransport(out m_Server, out m_ServerEvents, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var ping = new ArraySegment(Encoding.ASCII.GetBytes("ping")); - m_Client1.Send(m_Client1.ServerClientId, ping, delivery); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - Assert.That(m_ServerEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); - - var pong = new ArraySegment(Encoding.ASCII.GetBytes("pong")); - m_Server.Send(m_ServerEvents[0].ClientID, pong, delivery); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_Client1Events); - - Assert.That(m_Client1Events[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); - - yield return null; - } - - // Check if can make a simple data exchange (both ways at a time). - [UnityTest] - public IEnumerator PingPongSimultaneous( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - InitializeTransport(out m_Server, out m_ServerEvents, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var ping = new ArraySegment(Encoding.ASCII.GetBytes("ping")); - m_Server.Send(m_ServerEvents[0].ClientID, ping, delivery); - m_Client1.Send(m_Client1.ServerClientId, ping, delivery); - - // Once one event is in the other should be too. - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - Assert.That(m_ServerEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); - Assert.That(m_Client1Events[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); - - var pong = new ArraySegment(Encoding.ASCII.GetBytes("pong")); - m_Server.Send(m_ServerEvents[0].ClientID, pong, delivery); - m_Client1.Send(m_Client1.ServerClientId, pong, delivery); - - // Once one event is in the other should be too. - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - Assert.That(m_ServerEvents[2].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); - Assert.That(m_Client1Events[2].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); - - yield return null; - } - - // Test is ignored on Switch, PS4, and PS5 because on these platforms the OS buffers for - // loopback traffic are too small for the amount of data sent in a single update here. - [UnityTest] - [UnityPlatform(exclude = new[] { RuntimePlatform.Switch, RuntimePlatform.PS4, RuntimePlatform.PS5 })] - public IEnumerator SendMaximumPayloadSize( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - // We want something that's over the old limit of ~44KB for reliable payloads. - var payloadSize = 64 * 1024; - - InitializeTransport(out m_Server, out m_ServerEvents, payloadSize, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, payloadSize, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var payloadData = new byte[payloadSize]; - for (int i = 0; i < payloadData.Length; i++) - { - payloadData[i] = (byte)i; - } - - var payload = new ArraySegment(payloadData); - m_Client1.Send(m_Client1.ServerClientId, payload, delivery); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents, MaxNetworkEventWaitTime * 4); - - Assert.AreEqual(payloadSize, m_ServerEvents[1].Data.Count); - - var receivedArray = m_ServerEvents[1].Data.Array; - var receivedArrayOffset = m_ServerEvents[1].Data.Offset; - for (int i = 0; i < payloadSize; i++) - { - Assert.AreEqual(payloadData[i], receivedArray[receivedArrayOffset + i]); - } - - yield return null; - } - - // Check making multiple sends to a client in a single frame. - [UnityTest] - public IEnumerator MultipleSendsSingleFrame( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - InitializeTransport(out m_Server, out m_ServerEvents, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data1 = new byte[10]; - data1[0] = 11; - m_Client1.Send(m_Client1.ServerClientId, new ArraySegment(data1), delivery); - - var data2 = new byte[3000]; - data2[0] = 22; - m_Client1.Send(m_Client1.ServerClientId, new ArraySegment(data2), delivery); - - var data3 = new byte[10]; - data3[0] = 33; - m_Client1.Send(m_Client1.ServerClientId, new ArraySegment(data3), delivery); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - Assert.AreEqual(4, m_ServerEvents.Count); - Assert.AreEqual(NetworkEvent.Data, m_ServerEvents[3].Type); - - Assert.AreEqual(11, m_ServerEvents[1].Data.First()); - Assert.AreEqual(10, m_ServerEvents[1].Data.Count); - - Assert.AreEqual(22, m_ServerEvents[2].Data.First()); - Assert.AreEqual(3000, m_ServerEvents[2].Data.Count); - - Assert.AreEqual(33, m_ServerEvents[3].Data.First()); - Assert.AreEqual(10, m_ServerEvents[3].Data.Count); - - yield return null; - } - - // Check sending data to multiple clients. - [UnityTest] - public IEnumerator SendMultipleClients( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - InitializeTransport(out m_Server, out m_ServerEvents, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, family: family); - InitializeTransport(out m_Client2, out m_Client2Events, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - m_Client2.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - if (m_Client2Events.Count == 0) - { - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client2Events); - } - - // Ensure we got both Connect events. - Assert.AreEqual(2, m_ServerEvents.Count); - - var data1 = new ArraySegment(new byte[] { 11 }); - m_Server.Send(m_ServerEvents[0].ClientID, data1, delivery); - - var data2 = new ArraySegment(new byte[] { 22 }); - m_Server.Send(m_ServerEvents[1].ClientID, data2, delivery); - - // Once one has received its data, the other should have too. - yield return WaitForNetworkEvent(NetworkEvent.Data, m_Client1Events); - - // Do make sure the other client got its Data event. - Assert.AreEqual(2, m_Client2Events.Count); - Assert.AreEqual(NetworkEvent.Data, m_Client2Events[1].Type); - - byte c1Data = m_Client1Events[1].Data.First(); - byte c2Data = m_Client2Events[1].Data.First(); - Assert.That((c1Data == 11 && c2Data == 22) || (c1Data == 22 && c2Data == 11)); - - yield return null; - } - - // Check receiving data from multiple clients. - [UnityTest] - public IEnumerator ReceiveMultipleClients( - [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, - [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) - { - InitializeTransport(out m_Server, out m_ServerEvents, family: family); - InitializeTransport(out m_Client1, out m_Client1Events, family: family); - InitializeTransport(out m_Client2, out m_Client2Events, family: family); - - m_Server.StartServer(); - m_Client1.StartClient(); - m_Client2.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - if (m_Client2Events.Count == 0) - { - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client2Events); - } - - var data1 = new ArraySegment(new byte[] { 11 }); - m_Client1.Send(m_Client1.ServerClientId, data1, delivery); - - var data2 = new ArraySegment(new byte[] { 22 }); - m_Client2.Send(m_Client2.ServerClientId, data2, delivery); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - // Make sure we got both data messages. - Assert.AreEqual(4, m_ServerEvents.Count); - Assert.AreEqual(NetworkEvent.Data, m_ServerEvents[3].Type); - - byte sData1 = m_ServerEvents[2].Data.First(); - byte sData2 = m_ServerEvents[3].Data.First(); - Assert.That((sData1 == 11 && sData2 == 22) || (sData1 == 22 && sData2 == 11)); - - yield return null; - } - - // Check that we get disconnected when overflowing the reliable send queue. - [UnityTest] - public IEnumerator DisconnectOnReliableSendQueueOverflow() - { - const int maxSendQueueSize = 16 * 1024; - - InitializeTransport(out m_Server, out m_ServerEvents, maxSendQueueSize: maxSendQueueSize); - InitializeTransport(out m_Client1, out m_Client1Events, maxSendQueueSize: maxSendQueueSize); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - m_Server.Shutdown(); - - var numSends = (maxSendQueueSize / 1024); - - for (int i = 0; i < numSends; i++) - { - var payload = new ArraySegment(new byte[1024]); - m_Client1.Send(m_Client1.ServerClientId, payload, NetworkDelivery.Reliable); - } - - LogAssert.Expect(LogType.Error, "Couldn't add payload of size 1024 to reliable send queue. " + - $"Closing connection {m_Client1.ServerClientId} as reliability guarantees can't be maintained."); - - Assert.AreEqual(2, m_Client1Events.Count); - Assert.AreEqual(NetworkEvent.Disconnect, m_Client1Events[1].Type); - - yield return null; - } - - // Check that it's fine to overflow the unreliable send queue (traffic is flushed on overflow). - // Test is ignored on Switch, PS4, and PS5 because on these platforms the OS buffers for - // loopback traffic are too small for the amount of data sent in a single update here. - [UnityTest] - [UnityPlatform(exclude = new[] { RuntimePlatform.Switch, RuntimePlatform.PS4, RuntimePlatform.PS5 })] - public IEnumerator SendCompletesOnUnreliableSendQueueOverflow() - { - const int maxSendQueueSize = 16 * 1024; - - InitializeTransport(out m_Server, out m_ServerEvents, maxSendQueueSize: maxSendQueueSize); - InitializeTransport(out m_Client1, out m_Client1Events, maxSendQueueSize: maxSendQueueSize); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var numSends = (maxSendQueueSize / 1024) + 1; - - for (int i = 0; i < numSends; i++) - { - var payload = new ArraySegment(new byte[1024]); - m_Client1.Send(m_Client1.ServerClientId, payload, NetworkDelivery.Unreliable); - } - - // Manually wait. This ends up generating quite a bit of packets and it might take a - // while for everything to make it to the server. - yield return new WaitForSeconds(numSends * 0.02f); - - // Extra event is the connect event. - Assert.AreEqual(numSends + 1, m_ServerEvents.Count); - - for (int i = 1; i <= numSends; i++) - { - Assert.AreEqual(NetworkEvent.Data, m_ServerEvents[i].Type); - Assert.AreEqual(1024, m_ServerEvents[i].Data.Count); - } - - yield return null; - } - -#if !UTP_TRANSPORT_2_0_ABOVE - // Check that simulator parameters are effective. We only check with the drop rate, because - // that's easy to check and we only really want to make sure the simulator parameters are - // configured properly (the simulator pipeline stage is already well-tested in UTP). - [UnityTest] - [UnityPlatform(include = new[] { RuntimePlatform.OSXEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.LinuxEditor })] - public IEnumerator SimulatorParametersAreEffective() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.SetDebugSimulatorParameters(0, 0, 100); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data = new ArraySegment(new byte[] { 42 }); - m_Client1.Send(m_Client1.ServerClientId, data, NetworkDelivery.Reliable); - - yield return new WaitForSeconds(MaxNetworkEventWaitTime); - - Assert.AreEqual(1, m_ServerEvents.Count); - - yield return null; - } - - // Check that RTT is reported correctly. - [UnityTest] - [UnityPlatform(include = new[] { RuntimePlatform.OSXEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.LinuxEditor })] - public IEnumerator CurrentRttReportedCorrectly() - { - const int simulatedRtt = 25; - - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.SetDebugSimulatorParameters(simulatedRtt, 0, 0); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data = new ArraySegment(new byte[] { 42 }); - m_Client1.Send(m_Client1.ServerClientId, data, NetworkDelivery.Reliable); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents, - timeout: MaxNetworkEventWaitTime + (2 * simulatedRtt)); - - Assert.GreaterOrEqual(m_Client1.GetCurrentRtt(m_Client1.ServerClientId), simulatedRtt); - - yield return null; - } -#endif - - [UnityTest] - public IEnumerator SendQueuesFlushedOnShutdown([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data = new ArraySegment(new byte[] { 42 }); - m_Client1.Send(m_Client1.ServerClientId, data, delivery); - - m_Client1.Shutdown(); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - yield return null; - } - - [UnityTest] - public IEnumerator SendQueuesFlushedOnLocalClientDisconnect([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data = new ArraySegment(new byte[] { 42 }); - m_Client1.Send(m_Client1.ServerClientId, data, delivery); - - m_Client1.DisconnectLocalClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_ServerEvents); - - yield return null; - } - - [UnityTest] - public IEnumerator SendQueuesFlushedOnRemoteClientDisconnect([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var data = new ArraySegment(new byte[] { 42 }); - m_Server.Send(m_Client1.ServerClientId, data, delivery); - - m_Server.DisconnectRemoteClient(m_ServerEvents[0].ClientID); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_Client1Events); - - yield return null; - } - - [UnityTest] - public IEnumerator ReliablePayloadsCanBeLargerThanMaximum() - { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - - m_Server.StartServer(); - m_Client1.StartClient(); - - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); - - var payloadSize = UnityTransport.InitialMaxPayloadSize + 1; - var data = new ArraySegment(new byte[payloadSize]); - - m_Server.Send(m_Client1.ServerClientId, data, NetworkDelivery.Reliable); - - yield return WaitForNetworkEvent(NetworkEvent.Data, m_Client1Events); - - yield return null; - } - } -} diff --git a/Tests/Runtime/Transports/UnityTransportTests.cs.meta b/Tests/Runtime/Transports/UnityTransportTests.cs.meta deleted file mode 100644 index c27f4e2..0000000 --- a/Tests/Runtime/Transports/UnityTransportTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 66e054c3619ad4bd982e351eb8d63087 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Runtime/UniversalRpcTests.cs b/Tests/Runtime/UniversalRpcTests.cs deleted file mode 100644 index 3aeb06d..0000000 --- a/Tests/Runtime/UniversalRpcTests.cs +++ /dev/null @@ -1,2132 +0,0 @@ -#if !MULTIPLAYER_TOOLS && !NGO_MINIMALPROJECT -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using NUnit.Framework; -using Unity.Collections; -using Unity.Netcode.TestHelpers.Runtime; -using UnityEngine; -using Object = UnityEngine.Object; -using Random = System.Random; - -// NOTE: -// Unity's test runner cannot handle a single test fixture with thousands of tests in it. -// Since this file contains thousands of tests (once all parameters have been taken into account), -// I had to split up the tests into separate fixtures for each test case. -// That was the only way to get Unity to actually be able to handle this number of tests. -// I put them in their own namespace so they would be easier to navigate in the test list. -namespace Unity.Netcode.RuntimeTests.UniversalRpcTests -{ - internal class UniversalRpcNetworkBehaviour : NetworkBehaviour - { - public bool Stop = false; - public string Received = string.Empty; - public Tuple ReceivedParams = null; - public ulong ReceivedFrom = ulong.MaxValue; - public int ReceivedCount; - - public void OnRpcReceived() - { - var st = new StackTrace(); - var sf = st.GetFrame(1); - - var currentMethod = sf.GetMethod(); - Received = currentMethod.Name; - ReceivedCount++; - } - public void OnRpcReceivedWithParams(int a, bool b, float f, string s) - { - var st = new StackTrace(); - var sf = st.GetFrame(1); - - var currentMethod = sf.GetMethod(); - Received = currentMethod.Name; - ReceivedCount++; - ReceivedParams = new Tuple(a, b, f, s); - } - - // Basic RPCs - - [Rpc(SendTo.Everyone)] - public void DefaultToEveryoneRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Me)] - public void DefaultToMeRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Owner)] - public void DefaultToOwnerRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotOwner)] - public void DefaultToNotOwnerRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Server)] - public void DefaultToServerRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotMe)] - public void DefaultToNotMeRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotServer)] - public void DefaultToNotServerRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.ClientsAndHost)] - public void DefaultToClientsAndHostRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Authority)] - public void DefaultToAuthorityRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotAuthority)] - public void DefaultToNotAuthorityRpc() - { - OnRpcReceived(); - } - - // RPCs with parameters - - [Rpc(SendTo.Everyone)] - public void DefaultToEveryoneWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Me)] - public void DefaultToMeWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Owner)] - public void DefaultToOwnerWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotOwner)] - public void DefaultToNotOwnerWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Server)] - public void DefaultToServerWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotMe)] - public void DefaultToNotMeWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotServer)] - public void DefaultToNotServerWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.ClientsAndHost)] - public void DefaultToClientsAndHostWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Authority)] - public void DefaultToAuthorityWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotAuthority)] - public void DefaultToNotAuthorityWithParamsRpc(int i, bool b, float f, string s) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - // RPCs with RPC parameters - - [Rpc(SendTo.Everyone)] - public void DefaultToEveryoneWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.Me)] - public void DefaultToMeWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.Owner)] - public void DefaultToOwnerWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.NotOwner)] - public void DefaultToNotOwnerWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.Server)] - public void DefaultToServerWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.NotMe)] - public void DefaultToNotMeWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.NotServer)] - public void DefaultToNotServerWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.ClientsAndHost)] - public void DefaultToClientsAndHostWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.Authority)] - public void DefaultToAuthorityWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - [Rpc(SendTo.NotAuthority)] - public void DefaultToNotAuthorityWithRpcParamsRpc(RpcParams rpcParams) - { - OnRpcReceived(); - ReceivedFrom = rpcParams.Receive.SenderClientId; - } - - // RPCs with parameters and RPC parameters - - [Rpc(SendTo.Everyone)] - public void DefaultToEveryoneWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Me)] - public void DefaultToMeWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Owner)] - public void DefaultToOwnerWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotOwner)] - public void DefaultToNotOwnerWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Server)] - public void DefaultToServerWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotMe)] - public void DefaultToNotMeWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotServer)] - public void DefaultToNotServerWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.ClientsAndHost)] - public void DefaultToClientsAndHostWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.Authority)] - public void DefaultToAuthorityWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - [Rpc(SendTo.NotAuthority)] - public void DefaultToNotAuthorityWithParamsAndRpcParamsRpc(int i, bool b, float f, string s, RpcParams rpcParams) - { - OnRpcReceivedWithParams(i, b, f, s); - } - - // RPCs with AllowTargetOverride = true - - // AllowTargetOverried is implied with SpecifiedInParams and does not need to be stated - // Including it will cause a compiler warning - [Rpc(SendTo.SpecifiedInParams)] - public void DefaultToSpecifiedInParamsAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Everyone, AllowTargetOverride = true)] - public void DefaultToEveryoneAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Me, AllowTargetOverride = true)] - public void DefaultToMeAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Owner, AllowTargetOverride = true)] - public void DefaultToOwnerAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotOwner, AllowTargetOverride = true)] - public void DefaultToNotOwnerAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Server, AllowTargetOverride = true)] - public void DefaultToServerAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotMe, AllowTargetOverride = true)] - public void DefaultToNotMeAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotServer, AllowTargetOverride = true)] - public void DefaultToNotServerAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.ClientsAndHost, AllowTargetOverride = true)] - public void DefaultToClientsAndHostAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Authority, AllowTargetOverride = true)] - public void DefaultToAuthorityAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotAuthority, AllowTargetOverride = true)] - public void DefaultToNotAuthorityAllowOverrideRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - // RPCs with DeferLocal = true - - [Rpc(SendTo.Everyone, DeferLocal = true)] - public void DefaultToEveryoneDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Me, DeferLocal = true)] - public void DefaultToMeDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Owner, DeferLocal = true)] - public void DefaultToOwnerDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotOwner, DeferLocal = true)] - public void DefaultToNotOwnerDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Server, DeferLocal = true)] - public void DefaultToServerDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotServer, DeferLocal = true)] - public void DefaultToNotServerDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.ClientsAndHost, DeferLocal = true)] - public void DefaultToClientsAndHostDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Authority, DeferLocal = true)] - public void DefaultToAuthorityDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotAuthority, DeferLocal = true)] - public void DefaultToNotAuthorityDeferLocalRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - // RPCs with RequireOwnership = true - - [Rpc(SendTo.Everyone, RequireOwnership = true)] - public void DefaultToEveryoneRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Me, RequireOwnership = true)] - public void DefaultToMeRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Owner, RequireOwnership = true)] - public void DefaultToOwnerRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotOwner, RequireOwnership = true)] - public void DefaultToNotOwnerRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.Server, RequireOwnership = true)] - public void DefaultToServerRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotMe, RequireOwnership = true)] - public void DefaultToNotMeRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotServer, RequireOwnership = true)] - public void DefaultToNotServerRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.ClientsAndHost, RequireOwnership = true)] - public void DefaultToClientsAndHostRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.SpecifiedInParams, RequireOwnership = true)] - public void SpecifiedInParamsRequireOwnershipRpc(RpcParams rpcParams) - { - OnRpcReceived(); - } - - [Rpc(SendTo.Authority, RequireOwnership = true)] - public void DefaultToAuthorityRequireOwnershipRpc() - { - OnRpcReceived(); - } - - [Rpc(SendTo.NotAuthority, RequireOwnership = true)] - public void DefaultToNotAuthorityRequireOwnershipRpc() - { - OnRpcReceived(); - } - - // Mutual RPC Recursion - - [Rpc(SendTo.Server, DeferLocal = true)] - public void MutualRecursionServerRpc() - { - if (Stop) - { - Stop = false; - return; - } - OnRpcReceived(); - MutualRecursionClientRpc(); - } - - [Rpc(SendTo.NotServer, DeferLocal = true)] - public void MutualRecursionClientRpc() - { - OnRpcReceived(); - MutualRecursionServerRpc(); - } - - // Self recursion - [Rpc(SendTo.Server, DeferLocal = true)] - public void SelfRecursiveRpc() - { - if (Stop) - { - Stop = false; - return; - } - OnRpcReceived(); - SelfRecursiveRpc(); - } - } - - internal class UniversalRpcTestsBase : NetcodeIntegrationTest - { - protected override int NumberOfClients => 2; - - public UniversalRpcTestsBase(HostOrServer hostOrServer) : base(hostOrServer) - { - } - - - protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() - { - return NetworkManagerInstatiationMode.AllTests; - } - - protected override bool m_EnableTimeTravel => true; - - protected override bool m_SetupIsACoroutine => false; - protected override bool m_TearDownIsACoroutine => false; - - protected GameObject m_ServerObject; - - protected override void OnCreatePlayerPrefab() - { - m_PlayerPrefab.AddComponent(); - } - - protected override void OnServerAndClientsCreated() - { - m_ServerObject = new GameObject { name = "Server Object" }; - var networkObject = m_ServerObject.AddComponent(); - 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() - { - Clear(); - } - - protected void Clear() - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - obj.Received = string.Empty; - obj.ReceivedCount = 0; - obj.ReceivedParams = null; - obj.ReceivedFrom = ulong.MaxValue; - } - } - - protected override void OnOneTimeTearDown() - { - Object.DestroyImmediate(m_ServerObject); - } - - protected override void OnTimeTravelServerAndClientsConnected() - { - m_ServerObject.GetComponent().Spawn(); - WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList()); - } - - protected UniversalRpcNetworkBehaviour GetPlayerObject(ulong ownerClientId, ulong onClient) - { - if (ownerClientId == NetworkManager.ServerClientId && !m_ServerNetworkManager.IsHost) - { - foreach (var obj in Object.FindObjectsByType(FindObjectsSortMode.None)) - { - if (obj.name.StartsWith("Server Object") && obj.OwnerClientId == ownerClientId && obj.NetworkManager.LocalClientId == onClient) - { - return obj; - } - } - } - - return m_PlayerNetworkObjects[onClient][ownerClientId].GetComponent(); - } - - protected void VerifyLocalReceived(ulong objectOwner, ulong sender, string name, bool verifyReceivedFrom, int expectedReceived = 1) - { - var obj = GetPlayerObject(objectOwner, sender); - Assert.AreEqual(name, obj.Received); - Assert.That(obj.ReceivedCount, Is.EqualTo(expectedReceived)); - Assert.IsNull(obj.ReceivedParams); - if (verifyReceivedFrom) - { - Assert.AreEqual(sender, obj.ReceivedFrom); - } - } - - protected void VerifyLocalReceivedWithParams(ulong objectOwner, ulong sender, string name, int i, bool b, float f, string s) - { - var obj = GetPlayerObject(objectOwner, sender); - Assert.AreEqual(name, obj.Received); - Assert.That(obj.ReceivedCount, Is.EqualTo(1)); - Assert.IsNotNull(obj.ReceivedParams); - Assert.AreEqual(i, obj.ReceivedParams.Item1); - Assert.AreEqual(b, obj.ReceivedParams.Item2); - Assert.AreEqual(f, obj.ReceivedParams.Item3); - Assert.AreEqual(s, obj.ReceivedParams.Item4); - } - - protected void VerifyNotReceived(ulong objectOwner, ulong[] receivedBy) - { - foreach (var client in receivedBy) - { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); - Assert.AreEqual(string.Empty, playerObject.Received); - Assert.That(playerObject.ReceivedCount, Is.EqualTo(0)); - Assert.IsNull(playerObject.ReceivedParams); - } - } - - protected void VerifyRemoteReceived(ulong objectOwner, ulong sender, string message, ulong[] receivedBy, bool verifyReceivedFrom, bool waitForMessages = true, int expectedReceived = 1) - { - foreach (var client in receivedBy) - { - if (client == sender) - { - VerifyLocalReceived(objectOwner, sender, message, verifyReceivedFrom, expectedReceived); - - break; - } - } - - if (waitForMessages) - { - var needsProxyMessage = false; - var needsServerRpcMessage = false; - if (sender != 0) - { - foreach (var client in receivedBy) - { - if (client == sender) - { - continue; - } - - if (client != 0) - { - needsProxyMessage = true; - } - else - { - needsServerRpcMessage = true; - } - } - } - - if (needsProxyMessage) - { - var messages = new List { typeof(ProxyMessage) }; - if (needsServerRpcMessage) - { - messages.Add(typeof(RpcMessage)); - } - - WaitForMessagesReceivedWithTimeTravel(messages, new[] { m_ServerNetworkManager }.ToList()); - } - - var managersThatNeedToWaitForRpc = new List(); - if (needsServerRpcMessage && !needsProxyMessage) - { - managersThatNeedToWaitForRpc.Add(m_ServerNetworkManager); - } - - foreach (var client in receivedBy) - { - if (client != sender && client != 0) - { - managersThatNeedToWaitForRpc.Add(m_ClientNetworkManagers[client - 1]); - } - } - - WaitForMessageReceivedWithTimeTravel(managersThatNeedToWaitForRpc); - } - - foreach (var client in receivedBy) - { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); - Assert.AreEqual(message, playerObject.Received); - Assert.That(playerObject.ReceivedCount, Is.EqualTo(expectedReceived)); - Assert.IsNull(playerObject.ReceivedParams); - if (verifyReceivedFrom) - { - Assert.AreEqual(sender, playerObject.ReceivedFrom); - } - } - } - - protected void VerifyRemoteReceivedWithParams(ulong objectOwner, ulong sender, string message, ulong[] receivedBy, int i, bool b, float f, string s) - { - foreach (var client in receivedBy) - { - if (client == sender) - { - VerifyLocalReceivedWithParams(objectOwner, sender, message, i, b, f, s); - - break; - } - } - - var needsProxyMessage = false; - var needsServerRpcMessage = false; - if (sender != 0) - { - foreach (var client in receivedBy) - { - if (client == sender) - { - continue; - } - - if (client != 0) - { - needsProxyMessage = true; - } - else - { - needsServerRpcMessage = true; - } - } - } - - if (needsProxyMessage) - { - var messages = new List { typeof(ProxyMessage) }; - if (needsServerRpcMessage) - { - messages.Add(typeof(RpcMessage)); - } - - WaitForMessagesReceivedWithTimeTravel(messages, new[] { m_ServerNetworkManager }.ToList()); - } - - var managersThatNeedToWaitForRpc = new List(); - if (needsServerRpcMessage && !needsProxyMessage) - { - managersThatNeedToWaitForRpc.Add(m_ServerNetworkManager); - } - - foreach (var client in receivedBy) - { - if (client != sender && client != 0) - { - managersThatNeedToWaitForRpc.Add(m_ClientNetworkManagers[client - 1]); - } - } - - WaitForMessageReceivedWithTimeTravel(managersThatNeedToWaitForRpc); - - foreach (var client in receivedBy) - { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); - Assert.AreEqual(message, playerObject.Received); - Assert.That(playerObject.ReceivedCount, Is.EqualTo(1)); - - Assert.IsNotNull(playerObject.ReceivedParams); - Assert.AreEqual(i, playerObject.ReceivedParams.Item1); - Assert.AreEqual(b, playerObject.ReceivedParams.Item2); - Assert.AreEqual(f, playerObject.ReceivedParams.Item3); - Assert.AreEqual(s, playerObject.ReceivedParams.Item4); - } - } - - protected static ulong[] s_ClientIds = new[] { 0ul, 1ul, 2ul }; - - public void VerifySentToEveryone(ulong objectOwner, ulong sender, string methodName) - { - VerifyRemoteReceived(objectOwner, sender, methodName, s_ClientIds, false); - } - - public void VerifySentToEveryoneWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifyRemoteReceived(objectOwner, sender, methodName, s_ClientIds, true); - } - - public void VerifySentToEveryoneWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifyRemoteReceivedWithParams(objectOwner, sender, methodName, s_ClientIds, i, b, f, s); - } - - public void VerifySentToId(ulong objectOwner, ulong sender, ulong receiver, string methodName, bool verifyReceivedFrom) - { - VerifyRemoteReceived(objectOwner, sender, methodName, new[] { receiver }, verifyReceivedFrom); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => c != receiver).ToArray()); - - // Pass some time to make sure that no other client ever receives this - TimeTravel(1f, 30); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => c != receiver).ToArray()); - } - - public void VerifySentToNotId(ulong objectOwner, ulong sender, ulong notReceiver, string methodName, bool verifyReceivedFrom) - { - VerifyNotReceived(objectOwner, new[] { notReceiver }); - VerifyRemoteReceived(objectOwner, sender, methodName, s_ClientIds.Where(c => c != notReceiver).ToArray(), verifyReceivedFrom); - // Verify again after all the waiting is finished - VerifyNotReceived(objectOwner, new[] { notReceiver }); - } - - public void VerifySentToIdWithParams(ulong objectOwner, ulong sender, ulong receiver, string methodName, int i, bool b, float f, string s) - { - VerifyRemoteReceivedWithParams(objectOwner, sender, methodName, new[] { receiver }, i, b, f, s); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => c != receiver).ToArray()); - - // Pass some time to make sure that no other client ever receives this - TimeTravel(1f, 30); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => c != receiver).ToArray()); - } - - public void VerifySentToNotIdWithParams(ulong objectOwner, ulong sender, ulong notReceiver, string methodName, int i, bool b, float f, string s) - { - VerifyNotReceived(objectOwner, new[] { notReceiver }); - VerifyRemoteReceivedWithParams(objectOwner, sender, methodName, s_ClientIds.Where(c => c != notReceiver).ToArray(), i, b, f, s); - // Verify again after all the waiting is finished - VerifyNotReceived(objectOwner, new[] { notReceiver }); - } - - public void VerifySentToOwner(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, objectOwner, methodName, false); - } - - public void VerifySentToNotOwner(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, objectOwner, methodName, false); - } - - public void VerifySentToServer(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, NetworkManager.ServerClientId, methodName, false); - } - - public void VerifySentToNotServer(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, NetworkManager.ServerClientId, methodName, false); - } - - public void VerifySentToClientsAndHost(ulong objectOwner, ulong sender, string methodName) - { - if (m_ServerNetworkManager.IsHost) - { - VerifySentToEveryone(objectOwner, sender, methodName); - } - else - { - VerifySentToNotServer(objectOwner, sender, methodName); - } - } - - public void VerifySentToMe(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, sender, methodName, false); - } - - public void VerifySentToNotMe(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, sender, methodName, false); - } - - public void VerifySentToAuthority(ulong objectOwner, ulong sender, string methodName) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToId(objectOwner, sender, receiver, methodName, false); - } - - public void VerifySentToNotAuthority(ulong objectOwner, ulong sender, string methodName) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToNotId(objectOwner, sender, receiver, methodName, false); - } - - public void VerifySentToOwnerWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, objectOwner, methodName, true); - } - - public void VerifySentToNotOwnerWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, objectOwner, methodName, true); - } - - public void VerifySentToServerWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, NetworkManager.ServerClientId, methodName, true); - } - - public void VerifySentToNotServerWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, NetworkManager.ServerClientId, methodName, true); - } - - public void VerifySentToClientsAndHostWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - if (m_ServerNetworkManager.IsHost) - { - VerifySentToEveryoneWithReceivedFrom(objectOwner, sender, methodName); - } - else - { - VerifySentToNotServerWithReceivedFrom(objectOwner, sender, methodName); - } - } - - public void VerifySentToMeWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToId(objectOwner, sender, sender, methodName, true); - } - - public void VerifySentToNotMeWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - VerifySentToNotId(objectOwner, sender, sender, methodName, true); - } - - public void VerifySentToAuthorityWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToId(objectOwner, sender, receiver, methodName, true); - } - - public void VerifySentToNotAuthorityWithReceivedFrom(ulong objectOwner, ulong sender, string methodName) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToNotId(objectOwner, sender, receiver, methodName, true); - } - - public void VerifySentToOwnerWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToIdWithParams(objectOwner, sender, objectOwner, methodName, i, b, f, s); - } - - public void VerifySentToNotOwnerWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToNotIdWithParams(objectOwner, sender, objectOwner, methodName, i, b, f, s); - } - - public void VerifySentToServerWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToIdWithParams(objectOwner, sender, NetworkManager.ServerClientId, methodName, i, b, f, s); - } - - public void VerifySentToNotServerWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToNotIdWithParams(objectOwner, sender, NetworkManager.ServerClientId, methodName, i, b, f, s); - } - - public void VerifySentToClientsAndHostWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - if (m_ServerNetworkManager.IsHost) - { - VerifySentToEveryoneWithParams(objectOwner, sender, methodName, i, b, f, s); - } - else - { - VerifySentToNotServerWithParams(objectOwner, sender, methodName, i, b, f, s); - } - } - - public void VerifySentToMeWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToIdWithParams(objectOwner, sender, sender, methodName, i, b, f, s); - } - - public void VerifySentToNotMeWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - VerifySentToNotIdWithParams(objectOwner, sender, sender, methodName, i, b, f, s); - } - - public void VerifySentToAuthorityWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToIdWithParams(objectOwner, sender, receiver, methodName, i, b, f, s); - } - - public void VerifySentToNotAuthorityWithParams(ulong objectOwner, ulong sender, string methodName, int i, bool b, float f, string s) - { - var receiver = objectOwner; - if (!m_DistributedAuthority) - { - receiver = NetworkManager.ServerClientId; - } - VerifySentToNotIdWithParams(objectOwner, sender, receiver, methodName, i, b, f, s); - } - - public void RethrowTargetInvocationException(Action action) - { - try - { - action.Invoke(); - } - catch (TargetInvocationException e) - { - throw e.InnerException; - } - } - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingNoOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingNoOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [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.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - var sendMethodName = $"DefaultTo{sendTo}Rpc"; - var verifyMethodName = $"VerifySentTo{sendTo}"; - - var senderObject = GetPlayerObject(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 }); - } - - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSenderClientId : UniversalRpcTestsBase - { - public UniversalRpcTestSenderClientId(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSenderClientId( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost, SendTo.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - var sendMethodName = $"DefaultTo{sendTo}WithRpcParamsRpc"; - var verifyMethodName = $"VerifySentTo{sendTo}WithReceivedFrom"; - - var senderObject = GetPlayerObject(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 }); - } - - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingNoOverrideWithParams : UniversalRpcTestsBase - { - public UniversalRpcTestSendingNoOverrideWithParams(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSendingNoOverrideWithParams( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost, SendTo.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] 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 = GetPlayerObject(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 }); - } - - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingNoOverrideWithParamsAndRpcParams : UniversalRpcTestsBase - { - public UniversalRpcTestSendingNoOverrideWithParamsAndRpcParams(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSendingNoOverrideWithParamsAndRpcParams( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost, SendTo.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] 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 = GetPlayerObject(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 }); - } - - } - - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestRequireOwnership : UniversalRpcTestsBase - { - public UniversalRpcTestRequireOwnership(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestRequireOwnership( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost, SendTo.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - var sendMethodName = $"DefaultTo{sendTo}RequireOwnershipRpc"; - - var senderObject = GetPlayerObject(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 }); - } - } - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestDisallowedOverride : UniversalRpcTestsBase - { - public UniversalRpcTestDisallowedOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - // Add both authority and nonauthority - [Test] - public void TestDisallowedOverride( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost, SendTo.Authority, SendTo.NotAuthority)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender) - { - var senderObject = GetPlayerObject(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) }))); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingWithTargetOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingWithTargetOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - // Look at the implementations and add both - [Test] - public void TestSendingWithTargetOverride( - [Values] SendTo defaultSendTo, - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost)] SendTo overrideSendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; - var targetField = typeof(RpcTarget).GetField(overrideSendTo.ToString()); - var verifyMethodName = $"VerifySentTo{overrideSendTo}"; - - var senderObject = GetPlayerObject(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 }); - } - - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingWithSingleOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingWithSingleOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSendingWithSingleOverride( - [Values] SendTo defaultSendTo, - [Values(0u, 1u, 2u)] ulong recipient, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - 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 }); - - 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()); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingWithSingleNotOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingWithSingleNotOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSendingWithSingleNotOverride( - [Values] SendTo defaultSendTo, - [Values(0u, 1u, 2u)] ulong recipient, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) - { - 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 }); - - 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 }); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingWithGroupOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingWithGroupOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - public static ulong[][] RecipientGroups = new[] - { - new[] { 0ul }, - new[] { 1ul }, - new[] { 0ul, 1ul }, - new[] { 0ul, 1ul, 2ul } - }; - - public enum AllocationType - { - Array, - NativeArray, - NativeList, - List - } - - [Test] - public void TestSendingWithGroupOverride( - [Values] SendTo defaultSendTo, - [ValueSource(nameof(RecipientGroups))] ulong[] recipient, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender, - [Values] AllocationType allocationType - ) - { - var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; - - var senderObject = GetPlayerObject(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()); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSendingWithGroupNotOverride : UniversalRpcTestsBase - { - public UniversalRpcTestSendingWithGroupNotOverride(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - public static ulong[][] RecipientGroups = new[] - { - new ulong[] {}, - new[] { 0ul }, - new[] { 1ul }, - new[] { 0ul, 1ul }, - }; - - public enum AllocationType - { - Array, - NativeArray, - NativeList, - List - } - - [Test] - public void TestSendingWithGroupNotOverride( - [Values] SendTo defaultSendTo, - [ValueSource(nameof(RecipientGroups))] ulong[] recipient, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender, - [Values] AllocationType allocationType - ) - { - var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; - - var senderObject = GetPlayerObject(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()); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner : UniversalRpcTestsBase - { - public UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - } - - [TestFixture(HostOrServer.DAHost)] - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestDeferLocal : UniversalRpcTestsBase - { - public UniversalRpcTestDeferLocal(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - // All the test cases that involve sends that will be delivered locally - [TestCase(SendTo.Everyone, 0u, 0u)] - [TestCase(SendTo.Everyone, 0u, 1u)] - [TestCase(SendTo.Everyone, 0u, 2u)] - [TestCase(SendTo.Everyone, 1u, 0u)] - [TestCase(SendTo.Everyone, 1u, 1u)] - [TestCase(SendTo.Everyone, 1u, 2u)] - [TestCase(SendTo.Everyone, 2u, 0u)] - [TestCase(SendTo.Everyone, 2u, 1u)] - [TestCase(SendTo.Everyone, 2u, 2u)] - [TestCase(SendTo.Me, 0u, 0u)] - [TestCase(SendTo.Me, 0u, 1u)] - [TestCase(SendTo.Me, 0u, 2u)] - [TestCase(SendTo.Me, 1u, 0u)] - [TestCase(SendTo.Me, 1u, 1u)] - [TestCase(SendTo.Me, 1u, 2u)] - [TestCase(SendTo.Me, 2u, 0u)] - [TestCase(SendTo.Me, 2u, 1u)] - [TestCase(SendTo.Me, 2u, 2u)] - [TestCase(SendTo.Owner, 0u, 0u)] - [TestCase(SendTo.Owner, 1u, 1u)] - [TestCase(SendTo.Owner, 2u, 2u)] - [TestCase(SendTo.Server, 0u, 0u)] - [TestCase(SendTo.Server, 1u, 0u)] - [TestCase(SendTo.Server, 2u, 0u)] - [TestCase(SendTo.NotOwner, 0u, 1u)] - [TestCase(SendTo.NotOwner, 0u, 2u)] - [TestCase(SendTo.NotOwner, 1u, 0u)] - [TestCase(SendTo.NotOwner, 1u, 2u)] - [TestCase(SendTo.NotOwner, 2u, 0u)] - [TestCase(SendTo.NotOwner, 2u, 1u)] - [TestCase(SendTo.NotServer, 0u, 1u)] - [TestCase(SendTo.NotServer, 0u, 2u)] - [TestCase(SendTo.NotServer, 1u, 1u)] - [TestCase(SendTo.NotServer, 1u, 2u)] - [TestCase(SendTo.NotServer, 2u, 1u)] - [TestCase(SendTo.NotServer, 2u, 2u)] - [TestCase(SendTo.ClientsAndHost, 0u, 0u)] - [TestCase(SendTo.ClientsAndHost, 0u, 1u)] - [TestCase(SendTo.ClientsAndHost, 0u, 2u)] - [TestCase(SendTo.ClientsAndHost, 1u, 0u)] - [TestCase(SendTo.ClientsAndHost, 1u, 1u)] - [TestCase(SendTo.ClientsAndHost, 1u, 2u)] - [TestCase(SendTo.ClientsAndHost, 2u, 0u)] - [TestCase(SendTo.ClientsAndHost, 2u, 1u)] - [TestCase(SendTo.ClientsAndHost, 2u, 2u)] - [TestCase(SendTo.Authority, 0u, 0u)] - [TestCase(SendTo.Authority, 1u, 1u)] - [TestCase(SendTo.Authority, 2u, 2u)] - [TestCase(SendTo.NotAuthority, 0u, 1u)] - [TestCase(SendTo.NotAuthority, 0u, 2u)] - [TestCase(SendTo.NotAuthority, 1u, 0u)] - [TestCase(SendTo.NotAuthority, 1u, 2u)] - [TestCase(SendTo.NotAuthority, 2u, 0u)] - [TestCase(SendTo.NotAuthority, 2u, 1u)] - public void TestDeferLocal( - SendTo defaultSendTo, - ulong objectOwner, - ulong sender - ) - { - if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost) - { - // Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored - // Just consider this case a success... - return; - } - - // Similar to above, since Server and NotServer are already tested we can consider this a success - if (!m_DistributedAuthority && defaultSendTo == SendTo.Authority || defaultSendTo == SendTo.NotAuthority) - { - return; - } - - var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc"; - var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); - var sendMethod = senderObject.GetType().GetMethod(sendMethodName); - sendMethod.Invoke(senderObject, new object[] { new RpcParams() }); - - VerifyNotReceived(objectOwner, new[] { sender }); - // Should be received on the next frame - SimulateOneFrame(); - VerifyLocalReceived(objectOwner, sender, sendMethodName, false); - - var verifyMethod = GetType().GetMethod(verifyMethodName); - verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); - } - - [Test] - // All the test cases that involve sends that will be delivered locally - [TestCase(SendTo.Everyone, 0u, 0u)] - [TestCase(SendTo.Everyone, 0u, 1u)] - [TestCase(SendTo.Everyone, 0u, 2u)] - [TestCase(SendTo.Everyone, 1u, 0u)] - [TestCase(SendTo.Everyone, 1u, 1u)] - [TestCase(SendTo.Everyone, 1u, 2u)] - [TestCase(SendTo.Everyone, 2u, 0u)] - [TestCase(SendTo.Everyone, 2u, 1u)] - [TestCase(SendTo.Everyone, 2u, 2u)] - [TestCase(SendTo.Me, 0u, 0u)] - [TestCase(SendTo.Me, 0u, 1u)] - [TestCase(SendTo.Me, 0u, 2u)] - [TestCase(SendTo.Me, 1u, 0u)] - [TestCase(SendTo.Me, 1u, 1u)] - [TestCase(SendTo.Me, 1u, 2u)] - [TestCase(SendTo.Me, 2u, 0u)] - [TestCase(SendTo.Me, 2u, 1u)] - [TestCase(SendTo.Me, 2u, 2u)] - [TestCase(SendTo.Owner, 0u, 0u)] - [TestCase(SendTo.Owner, 1u, 1u)] - [TestCase(SendTo.Owner, 2u, 2u)] - [TestCase(SendTo.Server, 0u, 0u)] - [TestCase(SendTo.Server, 1u, 0u)] - [TestCase(SendTo.Server, 2u, 0u)] - [TestCase(SendTo.NotOwner, 0u, 1u)] - [TestCase(SendTo.NotOwner, 0u, 2u)] - [TestCase(SendTo.NotOwner, 1u, 0u)] - [TestCase(SendTo.NotOwner, 1u, 2u)] - [TestCase(SendTo.NotOwner, 2u, 0u)] - [TestCase(SendTo.NotOwner, 2u, 1u)] - [TestCase(SendTo.NotServer, 0u, 1u)] - [TestCase(SendTo.NotServer, 0u, 2u)] - [TestCase(SendTo.NotServer, 1u, 1u)] - [TestCase(SendTo.NotServer, 1u, 2u)] - [TestCase(SendTo.NotServer, 2u, 1u)] - [TestCase(SendTo.NotServer, 2u, 2u)] - [TestCase(SendTo.ClientsAndHost, 0u, 0u)] - [TestCase(SendTo.ClientsAndHost, 0u, 1u)] - [TestCase(SendTo.ClientsAndHost, 0u, 2u)] - [TestCase(SendTo.ClientsAndHost, 1u, 0u)] - [TestCase(SendTo.ClientsAndHost, 1u, 1u)] - [TestCase(SendTo.ClientsAndHost, 1u, 2u)] - [TestCase(SendTo.ClientsAndHost, 2u, 0u)] - [TestCase(SendTo.ClientsAndHost, 2u, 1u)] - [TestCase(SendTo.ClientsAndHost, 2u, 2u)] - [TestCase(SendTo.Authority, 0u, 0u)] - [TestCase(SendTo.Authority, 1u, 1u)] - [TestCase(SendTo.Authority, 2u, 2u)] - [TestCase(SendTo.NotAuthority, 0u, 1u)] - [TestCase(SendTo.NotAuthority, 0u, 2u)] - [TestCase(SendTo.NotAuthority, 1u, 0u)] - [TestCase(SendTo.NotAuthority, 1u, 2u)] - [TestCase(SendTo.NotAuthority, 2u, 0u)] - [TestCase(SendTo.NotAuthority, 2u, 1u)] - public void TestDeferLocalOverrideToTrue( - SendTo defaultSendTo, - ulong objectOwner, - ulong sender - ) - { - if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost) - { - // Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored - // Just consider this case a success... - return; - } - // Similar to above, since Server and NotServer are already tested we can consider this a success - if (!m_DistributedAuthority && defaultSendTo == SendTo.Authority || defaultSendTo == SendTo.NotAuthority) - { - return; - } - - var sendMethodName = $"DefaultTo{defaultSendTo}WithRpcParamsRpc"; - var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); - var sendMethod = senderObject.GetType().GetMethod(sendMethodName); - sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.Defer }); - - VerifyNotReceived(objectOwner, new[] { sender }); - // Should be received on the next frame - SimulateOneFrame(); - VerifyLocalReceived(objectOwner, sender, sendMethodName, false); - - var verifyMethod = GetType().GetMethod(verifyMethodName); - verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); - } - - [Test] - // All the test cases that involve sends that will be delivered locally - [TestCase(SendTo.Everyone, 0u, 0u)] - [TestCase(SendTo.Everyone, 0u, 1u)] - [TestCase(SendTo.Everyone, 0u, 2u)] - [TestCase(SendTo.Everyone, 1u, 0u)] - [TestCase(SendTo.Everyone, 1u, 1u)] - [TestCase(SendTo.Everyone, 1u, 2u)] - [TestCase(SendTo.Everyone, 2u, 0u)] - [TestCase(SendTo.Everyone, 2u, 1u)] - [TestCase(SendTo.Everyone, 2u, 2u)] - [TestCase(SendTo.Me, 0u, 0u)] - [TestCase(SendTo.Me, 0u, 1u)] - [TestCase(SendTo.Me, 0u, 2u)] - [TestCase(SendTo.Me, 1u, 0u)] - [TestCase(SendTo.Me, 1u, 1u)] - [TestCase(SendTo.Me, 1u, 2u)] - [TestCase(SendTo.Me, 2u, 0u)] - [TestCase(SendTo.Me, 2u, 1u)] - [TestCase(SendTo.Me, 2u, 2u)] - [TestCase(SendTo.Owner, 0u, 0u)] - [TestCase(SendTo.Owner, 1u, 1u)] - [TestCase(SendTo.Owner, 2u, 2u)] - [TestCase(SendTo.Server, 0u, 0u)] - [TestCase(SendTo.Server, 1u, 0u)] - [TestCase(SendTo.Server, 2u, 0u)] - [TestCase(SendTo.NotOwner, 0u, 1u)] - [TestCase(SendTo.NotOwner, 0u, 2u)] - [TestCase(SendTo.NotOwner, 1u, 0u)] - [TestCase(SendTo.NotOwner, 1u, 2u)] - [TestCase(SendTo.NotOwner, 2u, 0u)] - [TestCase(SendTo.NotOwner, 2u, 1u)] - [TestCase(SendTo.NotServer, 0u, 1u)] - [TestCase(SendTo.NotServer, 0u, 2u)] - [TestCase(SendTo.NotServer, 1u, 1u)] - [TestCase(SendTo.NotServer, 1u, 2u)] - [TestCase(SendTo.NotServer, 2u, 1u)] - [TestCase(SendTo.NotServer, 2u, 2u)] - [TestCase(SendTo.ClientsAndHost, 0u, 0u)] - [TestCase(SendTo.ClientsAndHost, 0u, 1u)] - [TestCase(SendTo.ClientsAndHost, 0u, 2u)] - [TestCase(SendTo.ClientsAndHost, 1u, 0u)] - [TestCase(SendTo.ClientsAndHost, 1u, 1u)] - [TestCase(SendTo.ClientsAndHost, 1u, 2u)] - [TestCase(SendTo.ClientsAndHost, 2u, 0u)] - [TestCase(SendTo.ClientsAndHost, 2u, 1u)] - [TestCase(SendTo.ClientsAndHost, 2u, 2u)] - [TestCase(SendTo.Authority, 0u, 0u)] - [TestCase(SendTo.Authority, 1u, 1u)] - [TestCase(SendTo.Authority, 2u, 2u)] - [TestCase(SendTo.NotAuthority, 0u, 1u)] - [TestCase(SendTo.NotAuthority, 0u, 2u)] - [TestCase(SendTo.NotAuthority, 1u, 0u)] - [TestCase(SendTo.NotAuthority, 1u, 2u)] - [TestCase(SendTo.NotAuthority, 2u, 0u)] - [TestCase(SendTo.NotAuthority, 2u, 1u)] - public void TestDeferLocalOverrideToFalse( - SendTo defaultSendTo, - ulong objectOwner, - ulong sender - ) - { - if (defaultSendTo == SendTo.ClientsAndHost && sender == 0u && !m_ServerNetworkManager.IsHost) - { - // Not calling Assert.Ignore() because Unity will mark the whole block of tests as ignored - // Just consider this case a success... - return; - } - // Similar to above, since Server and NotServer are already tested we can consider this a success - if (!m_DistributedAuthority && defaultSendTo == SendTo.Authority || defaultSendTo == SendTo.NotAuthority) - { - return; - } - - var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc"; - var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); - var sendMethod = senderObject.GetType().GetMethod(sendMethodName); - sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.SendImmediate }); - - VerifyLocalReceived(objectOwner, sender, sendMethodName, false); - - var verifyMethod = GetType().GetMethod(verifyMethodName); - verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); - } - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestMutualRecursion : UniversalRpcTestsBase - { - public UniversalRpcTestMutualRecursion(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestMutualRecursion() - { - var serverObj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); - - serverObj.MutualRecursionClientRpc(); - - var serverIdArray = new[] { NetworkManager.ServerClientId }; - var clientIdArray = s_ClientIds.Where(c => c != NetworkManager.ServerClientId).ToArray(); - - var clientList = m_ClientNetworkManagers.ToList(); - var serverList = new List { m_ServerNetworkManager }; - - VerifyNotReceived(NetworkManager.ServerClientId, s_ClientIds); - - var clientListExpected = 1; - var serverListExpected = 2; - for (var i = 1; i <= 10; ++i) - { - WaitForMessageReceivedWithTimeTravel(clientList); - VerifyRemoteReceived(NetworkManager.ServerClientId, NetworkManager.ServerClientId, nameof(UniversalRpcNetworkBehaviour.MutualRecursionClientRpc), clientIdArray, false, false, clientListExpected); - VerifyNotReceived(NetworkManager.ServerClientId, serverIdArray); - clientListExpected *= 2; - - Clear(); - WaitForMessageReceivedWithTimeTravel(serverList); - VerifyRemoteReceived(NetworkManager.ServerClientId, NetworkManager.ServerClientId, nameof(UniversalRpcNetworkBehaviour.MutualRecursionServerRpc), serverIdArray, false, false, serverListExpected); - VerifyNotReceived(NetworkManager.ServerClientId, clientIdArray); - serverListExpected *= 2; - - Clear(); - } - serverObj.Stop = true; - WaitForMessageReceivedWithTimeTravel(serverList); - Assert.IsFalse(serverObj.Stop); - } - - - } - - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestSelfRecursion : UniversalRpcTestsBase - { - public UniversalRpcTestSelfRecursion(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - - [Test] - public void TestSelfRecursion() - { - var serverObj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); - - serverObj.SelfRecursiveRpc(); - - var serverIdArray = new[] { NetworkManager.ServerClientId }; - var clientIdArray = s_ClientIds.Where(c => c != NetworkManager.ServerClientId).ToArray(); - - var clientList = m_ClientNetworkManagers.ToList(); - var serverList = new List { m_ServerNetworkManager }; - - for (var i = 0; i < 10; ++i) - { - VerifyNotReceived(NetworkManager.ServerClientId, s_ClientIds); - SimulateOneFrame(); - VerifyLocalReceived(NetworkManager.ServerClientId, NetworkManager.ServerClientId, nameof(UniversalRpcNetworkBehaviour.SelfRecursiveRpc), false); - - Clear(); - } - - serverObj.Stop = true; - SimulateOneFrame(); - Assert.IsFalse(serverObj.Stop); - VerifyNotReceived(NetworkManager.ServerClientId, s_ClientIds); - } - - } - - [TestFixture(ObjType.Server)] - [TestFixture(ObjType.Client)] - internal class UniversalRpcTestRpcTargetUse : UniversalRpcTestsBase - { - private ObjType m_ObjType; - - public UniversalRpcTestRpcTargetUse(ObjType objType) : base(HostOrServer.Server) - { - m_ObjType = objType; - } - - public enum AllocationType - { - Array, - NativeArray, - NativeList, - List - } - private BaseRpcTarget GetGroup(NetworkBehaviour senderObject, ulong[] recipient, AllocationType allocationType, RpcTargetUse use) - { - switch (allocationType) - { - case AllocationType.Array: - return senderObject.RpcTarget.Group(recipient, use); - case AllocationType.List: - return senderObject.RpcTarget.Group(recipient.ToList(), use); - case AllocationType.NativeArray: - var arr = new NativeArray(recipient, Allocator.Temp); - var naTarget = senderObject.RpcTarget.Group(arr, use); - arr.Dispose(); - return naTarget; - 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); - } - var nlTarget = senderObject.RpcTarget.Group(list, use); - list.Dispose(); - return nlTarget; - } - - return null; - } - private BaseRpcTarget GetNot(NetworkBehaviour senderObject, ulong[] recipient, AllocationType allocationType, RpcTargetUse use) - { - switch (allocationType) - { - case AllocationType.Array: - return senderObject.RpcTarget.Not(recipient, use); - case AllocationType.List: - return senderObject.RpcTarget.Not(recipient.ToList(), use); - case AllocationType.NativeArray: - var arr = new NativeArray(recipient, Allocator.Temp); - var naTarget = senderObject.RpcTarget.Not(arr, use); - arr.Dispose(); - return naTarget; - 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); - } - var nlTarget = senderObject.RpcTarget.Not(list, use); - list.Dispose(); - return nlTarget; - } - - return null; - } - - public enum ObjType - { - Client, - Server - } - - private NetworkBehaviour m_Obj; - - protected override void OnTimeTravelServerAndClientsConnected() - { - base.OnTimeTravelServerAndClientsConnected(); - - if (m_ObjType == ObjType.Server) - { - m_Obj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); - } - else - { - m_Obj = GetPlayerObject(1, 1); - } - } - - [Test] - public void TestRpcTargetUseGroup([Values] AllocationType allocationType) - { - var group1 = GetGroup(m_Obj, new[] { 1ul, 2ul }, allocationType, RpcTargetUse.Temp); - var group2 = GetGroup(m_Obj, new[] { 2ul, 3ul }, allocationType, RpcTargetUse.Temp); - var group3 = GetGroup(m_Obj, new[] { 1ul, 2ul }, allocationType, RpcTargetUse.Persistent); - var group4 = GetGroup(m_Obj, new[] { 2ul, 3ul }, allocationType, RpcTargetUse.Persistent); - - Assert.AreSame(group1, group2); - Assert.AreNotSame(group1, group3); - Assert.AreNotSame(group1, group4); - Assert.AreNotSame(group2, group3); - Assert.AreNotSame(group2, group4); - Assert.AreNotSame(group3, group4); - - Assert.Throws(() => - { - group1.Dispose(); - }); - - Assert.Throws(() => - { - group2.Dispose(); - }); - - group3.Dispose(); - group4.Dispose(); - } - - [Test] - public void TestRpcTargetUseNotGroup([Values] AllocationType allocationType) - { - var not1 = GetNot(m_Obj, new[] { 1ul, 2ul }, allocationType, RpcTargetUse.Temp); - var not2 = GetNot(m_Obj, new[] { 2ul, 3ul }, allocationType, RpcTargetUse.Temp); - var not3 = GetNot(m_Obj, new[] { 1ul, 2ul }, allocationType, RpcTargetUse.Persistent); - var not4 = GetNot(m_Obj, new[] { 2ul, 3ul }, allocationType, RpcTargetUse.Persistent); - - Assert.AreSame(not1, not2); - Assert.AreNotSame(not1, not3); - Assert.AreNotSame(not1, not4); - Assert.AreNotSame(not2, not3); - Assert.AreNotSame(not2, not4); - Assert.AreNotSame(not3, not4); - - Assert.Throws(() => - { - not1.Dispose(); - }); - - Assert.Throws(() => - { - not2.Dispose(); - }); - - not3.Dispose(); - not4.Dispose(); - } - - [Test] - public void TestRpcTargetUseSingle() - { - // Not using 1 here because 1 is a special case that returns a LocalSendTarget for the client - // because the client versin of this test uses m_Obj from client ID 1 (ergo 1 is localhost in this test). - // So 1 will always be different from 2 and we want to verify the first two are the same. - var single1 = m_Obj.RpcTarget.Single(2ul, RpcTargetUse.Temp); - var single2 = m_Obj.RpcTarget.Single(3ul, RpcTargetUse.Temp); - var single3 = m_Obj.RpcTarget.Single(2ul, RpcTargetUse.Persistent); - var single4 = m_Obj.RpcTarget.Single(3ul, RpcTargetUse.Persistent); - Assert.AreSame(single1, single2); - Assert.AreNotSame(single1, single3); - Assert.AreNotSame(single1, single4); - Assert.AreNotSame(single2, single3); - Assert.AreNotSame(single2, single4); - Assert.AreNotSame(single3, single4); - - Assert.Throws(() => - { - single1.Dispose(); - }); - - Assert.Throws(() => - { - single2.Dispose(); - }); - - single3.Dispose(); - single4.Dispose(); - } - - [Test] - public void TestRpcTargetUseNotSingle() - { - var singleNot1 = m_Obj.RpcTarget.Not(1ul, RpcTargetUse.Temp); - var singleNot2 = m_Obj.RpcTarget.Not(2ul, RpcTargetUse.Temp); - var singleNot3 = m_Obj.RpcTarget.Not(1ul, RpcTargetUse.Persistent); - var singleNot4 = m_Obj.RpcTarget.Not(2ul, RpcTargetUse.Persistent); - Assert.AreSame(singleNot1, singleNot2); - Assert.AreNotSame(singleNot1, singleNot3); - Assert.AreNotSame(singleNot1, singleNot4); - Assert.AreNotSame(singleNot2, singleNot3); - Assert.AreNotSame(singleNot2, singleNot4); - Assert.AreNotSame(singleNot3, singleNot4); - - Assert.Throws(() => - { - singleNot1.Dispose(); - }); - - Assert.Throws(() => - { - singleNot2.Dispose(); - }); - - singleNot3.Dispose(); - singleNot4.Dispose(); - } - - } -} -#endif diff --git a/Tests/Runtime/UniversalRpcTests.cs.meta b/Tests/Runtime/UniversalRpcTests.cs.meta deleted file mode 100644 index 2564551..0000000 --- a/Tests/Runtime/UniversalRpcTests.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: af2b96a4f4d34fa798385b487fc5c97d -timeCreated: 1698158457 \ No newline at end of file diff --git a/Tests/Runtime/com.unity.netcode.runtimetests.asmdef b/Tests/Runtime/com.unity.netcode.runtimetests.asmdef deleted file mode 100644 index 72d85ca..0000000 --- a/Tests/Runtime/com.unity.netcode.runtimetests.asmdef +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "Unity.Netcode.RuntimeTests", - "rootNamespace": "Unity.Netcode.RuntimeTests", - "references": [ - "Unity.Netcode.Runtime", - "Unity.Netcode.Components", - "Unity.Collections", - "Unity.Multiplayer.MetricTypes", - "Unity.Multiplayer.NetStats", - "Unity.Multiplayer.Tools.MetricTypes", - "Unity.Multiplayer.Tools.NetStats", - "Unity.Networking.Transport", - "ClientNetworkTransform", - "Unity.Netcode.TestHelpers.Runtime", - "Unity.Mathematics", - "UnityEngine.TestRunner", - "UnityEditor.TestRunner" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": true, - "precompiledReferences": [ - "nunit.framework.dll" - ], - "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS", - "UNITY_INCLUDE_TESTS" - ], - "versionDefines": [ - { - "name": "com.unity.multiplayer.tools", - "expression": "", - "define": "MULTIPLAYER_TOOLS" - }, - { - "name": "Unity", - "expression": "(0,2022.2.0a5)", - "define": "UNITY_UNET_PRESENT" - }, - { - "name": "com.unity.multiplayer.tools", - "expression": "1.0.0-pre.7", - "define": "MULTIPLAYER_TOOLS_1_0_0_PRE_7" - }, - { - "name": "com.unity.modules.physics", - "expression": "", - "define": "COM_UNITY_MODULES_PHYSICS" - }, - { - "name": "com.unity.transport", - "expression": "2.0.0-exp", - "define": "UTP_TRANSPORT_2_0_ABOVE" - } - ], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Tests/Runtime/com.unity.netcode.runtimetests.asmdef.meta b/Tests/Runtime/com.unity.netcode.runtimetests.asmdef.meta deleted file mode 100644 index 1a5d075..0000000 --- a/Tests/Runtime/com.unity.netcode.runtimetests.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0d0243c226d5dab4fb5d34006a1ad53b -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ValidationExceptions.json b/ValidationExceptions.json deleted file mode 100644 index 9128292..0000000 --- a/ValidationExceptions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ErrorExceptions": [], - "WarningExceptions": [] -} diff --git a/ValidationExceptions.json.meta b/ValidationExceptions.json.meta deleted file mode 100644 index 3316cf2..0000000 --- a/ValidationExceptions.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 2a43005be301c9043aab7034757d4868 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/package.json b/package.json index 0ddc180..9804af5 100644 --- a/package.json +++ b/package.json @@ -2,23 +2,14 @@ "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": "2.1.1", + "version": "2.2.0", "unity": "6000.0", "dependencies": { "com.unity.nuget.mono-cecil": "1.11.4", - "com.unity.transport": "2.3.0" + "com.unity.transport": "2.4.0" }, - "_upm": { - "changelog": "### Added\n\n- Added ability to edit the `NetworkConfig.AutoSpawnPlayerPrefabClientSide` within the inspector view. (#3097)\n- Added `IContactEventHandlerWithInfo` that derives from `IContactEventHandler` that can be updated per frame to provide `ContactEventHandlerInfo` information to the `RigidbodyContactEventManager` when processing collisions. (#3094)\n - `ContactEventHandlerInfo.ProvideNonRigidBodyContactEvents`: When set to true, non-`Rigidbody` collisions with the registered `Rigidbody` will generate contact event notifications. (#3094)\n - `ContactEventHandlerInfo.HasContactEventPriority`: When set to true, the `Rigidbody` will be prioritized as the instance that generates the event if the `Rigidbody` colliding does not have priority. (#3094)\n- Added a static `NetworkManager.OnInstantiated` event notification to be able to track when a new `NetworkManager` instance has been instantiated. (#3088)\n- Added a static `NetworkManager.OnDestroying` event notification to be able to track when an existing `NetworkManager` instance is being destroyed. (#3088)\n\n### Fixed\n\n- Fixed issue where `NetworkPrefabProcessor` would not mark the prefab list as dirty and prevent saving the `DefaultNetworkPrefabs` asset when only imports or only deletes were detected.(#3103)\n- Fixed an issue where nested `NetworkTransform` components in owner authoritative mode cleared their initial settings on the server, causing improper synchronization. (#3099)\n- Fixed issue with service not getting synchronized with in-scene placed `NetworkObject` instances when a session owner starts a `SceneEventType.Load` event. (#3096)\n- Fixed issue with the in-scene network prefab instance update menu tool where it was not properly updating scenes when invoked on the root prefab instance. (#3092)\n- Fixed an issue where newly synchronizing clients would always receive current `NetworkVariable` values, potentially causing issues with collections if there were pending updates. Now, pending state updates serialize previous values to avoid duplicates on new clients. (#3081)\n- Fixed issue where changing ownership would mark every `NetworkVariable` dirty. Now, it will only mark any `NetworkVariable` with owner read permissions as dirty and will send/flush any pending updates to all clients prior to sending the change in ownership message. (#3081)\n- Fixed an issue where transferring ownership of `NetworkVariable` collections didn't update the new owner’s previous value, causing the last added value to be detected as a change during additions or removals. (#3081)\n- Fixed issue where a client (or server) with no write permissions for a `NetworkVariable` using a standard .NET collection type could still modify the collection which could cause various issues depending upon the modification and collection type. (#3081)\n- Fixed issue where applying the position and/or rotation to the `NetworkManager.ConnectionApprovalResponse` when connection approval and auto-spawn player prefab were enabled would not apply the position and/or rotation when the player prefab was instantiated. (#3078)\n- Fixed issue where `NetworkObject.SpawnWithObservers` was not being honored when spawning the player prefab. (#3077)\n- Fixed issue with the client count not being correct on the host or server side when a client disconnects itself from a session. (#3075)\n\n### Changed\n\n- Changed `NetworkConfig.AutoSpawnPlayerPrefabClientSide` is no longer automatically set when starting `NetworkManager`. (#3097)\n- Updated `NetworkVariableDeltaMessage` so the server now forwards delta state updates from clients immediately, instead of waiting until the end of the frame or the next network tick. (#3081)" - }, - "upmCi": { - "footprint": "8331c76150e539e36659d8b7be3ba0fb6d21027a" - }, - "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.1/manual/index.html", - "repository": { - "url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git", - "type": "git", - "revision": "264b30d176dd71fcedd022a8d6f4d59a2e3922bc" + "author": { + "name": "Unity" }, "samples": [ { @@ -27,7 +18,16 @@ "path": "Samples~/Bootstrap" } ], - "author": { - "name": "Unity" + "_upm": { + "changelog": "### Added\n\n- Added `NetworkObject.OwnershipStatus.SessionOwner` to allow Network Objects to be distributable and only owned by the Session Owner. This flag will override all other `OwnershipStatus` flags. (#3175)\n- Added `UnityTransport.GetEndpoint` method to provide a way to obtain `NetworkEndpoint` information of a connection via client identifier. (#3130)\n- Added `NetworkTransport.OnEarlyUpdate` and `NetworkTransport.OnPostLateUpdate` methods to provide more control over handling transport related events at the start and end of each frame. (#3113)\n\n### Fixed\n\n- Fixed issue where the server, host, or session owner would not populate the in-scene place `NetworkObject` table if the scene was loaded prior to starting the `NetworkManager`. (#3177)\n- Fixed issue where the `NetworkObjectIdHash` value could be incorrect when entering play mode while still in prefab edit mode with pending changes and using MPPM. (#3162)\n- Fixed issue where a sever only `NetworkManager` instance would spawn the actual `NetworkPrefab`'s `GameObject` as opposed to creating an instance of it. (#3160)\n- Fixed issue where only the session owner (as opposed to all clients) would handle spawning prefab overrides properly when using a distributed authority network topology. (#3160)\n- Fixed issue where an exception was thrown when calling `NetworkManager.Shutdown` after calling `UnityTransport.Shutdown`. (#3118)\n- Fixed issue where `NetworkList` properties on in-scene placed `NetworkObject`s could cause small memory leaks when entering playmode. (#3147)\n- Fixed in-scene `NertworkObject` synchronization issue when loading a scene with currently connected clients connected to a session created by a `NetworkManager` started as a server (i.e. not as a host). (#3133)\n- Fixed issue where a `NetworkManager` started as a server would not add itself as an observer to in-scene placed `NetworkObject`s instantiated and spawned by a scene loading event. (#3133)\n- Fixed issue where spawning a player using `NetworkObject.InstantiateAndSpawn` or `NetworkSpawnManager.InstantiateAndSpawn` would not update the `NetworkSpawnManager.PlayerObjects` or assign the newly spawned player to the `NetworkClient.PlayerObject`. (#3122)\n- Fixed issue where queued UnitTransport (NetworkTransport) message batches were being sent on the next frame. They are now sent at the end of the frame during `PostLateUpdate`. (#3113)\n- Fixed issue where `NotOwnerRpcTarget` or `OwnerRpcTarget` were not using their replacements `NotAuthorityRpcTarget` and `AuthorityRpcTarget` which would invoke a warning. (#3111)\n- Fixed issue where client is removed as an observer from spawned objects when their player instance is despawned. (#3110)\n- Fixed issue where `NetworkAnimator` would statically allocate write buffer space for `Animator` parameters that could cause a write error if the number of parameters exceeded the space allocated. (#3108)\n\n### Changed\n\n- In-scene placed `NetworkObject`s have been made distributable when balancing object distribution after a connection event. (#3175)\n- Optimised `NetworkVariable` and `NetworkTransform` related packets when in Distributed Authority mode.\n- The Debug Simulator section of the Unity Transport component was removed. This section was not functional anymore and users are now recommended to use the more featureful [Network Simulator](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/) tool from the Multiplayer Tools package instead. (#3121)" + }, + "upmCi": { + "footprint": "9d95aefc0dccf8f9dc0bcf0017dee417d7d31f56" + }, + "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.2/manual/index.html", + "repository": { + "url": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git", + "type": "git", + "revision": "ba490651a8c6cf2f98c2bbacef8b24a1170860b3" } }