using System; using NUnit.Framework; using Unity.Collections; using UnityEngine; using Unity.Netcode.TestHelpers.Runtime; namespace Unity.Netcode.RuntimeTests { public class ManagedNetworkSerializableType : INetworkSerializable, IEquatable { public string Str = ""; public int[] Ints = Array.Empty(); 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; } } 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; } } 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; } } public 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(); } } public struct UnmanagedTemplateNetworkSerializableType : INetworkSerializable where T : unmanaged, INetworkSerializable { public T Value; public void NetworkSerialize(BufferSerializer serializer) where TReaderWriterType : IReaderWriter { serializer.SerializeValue(ref Value); } } public 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((byte)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((sbyte)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 } }); // 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 } })); } // 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 } }; //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; } } } } } }