Skip to content

Commit 64c072e

Browse files
test
Adding test to validate single player works when started as a host and normal netcode functionality works. Adding tests to validate that NetworkManager will fail to start if started as a client or server when using the SinglePlayerTransport.
1 parent 8e7ddab commit 64c072e

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using NUnit.Framework;
5+
using Unity.Netcode.TestHelpers.Runtime;
6+
using UnityEngine;
7+
using UnityEngine.TestTools;
8+
using Random = UnityEngine.Random;
9+
10+
namespace Unity.Netcode.RuntimeTests
11+
{
12+
internal class SinglePlayerTransportTests : NetcodeIntegrationTest
13+
{
14+
protected override int NumberOfClients => 0;
15+
16+
public struct SerializableStruct : INetworkSerializable, IEquatable<SerializableStruct>
17+
{
18+
public bool BoolValue;
19+
public ulong ULongValue;
20+
21+
public bool Equals(SerializableStruct other)
22+
{
23+
return other.BoolValue == BoolValue && other.ULongValue == ULongValue;
24+
}
25+
26+
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
27+
{
28+
serializer.SerializeValue(ref BoolValue);
29+
serializer.SerializeValue(ref ULongValue);
30+
}
31+
}
32+
33+
public class SinglePlayerTestComponent : NetworkBehaviour
34+
{
35+
private enum SpawnStates
36+
{
37+
PreSpawn,
38+
Spawn,
39+
PostSpawn,
40+
}
41+
42+
private enum RpcInvocations
43+
{
44+
SendToServerRpc,
45+
SendToEveryoneRpc,
46+
SendToOwnerRpc,
47+
}
48+
49+
private Dictionary<SpawnStates, int> m_SpawnStateInvoked = new Dictionary<SpawnStates, int>();
50+
private Dictionary<RpcInvocations, int> m_RpcInvocations = new Dictionary<RpcInvocations, int>();
51+
private NetworkVariable<int> m_IntValue = new NetworkVariable<int>();
52+
private NetworkVariable<SerializableStruct> m_SerializableValue = new NetworkVariable<SerializableStruct>();
53+
54+
55+
private void SpawnStateInvoked(SpawnStates spawnState)
56+
{
57+
if (!m_SpawnStateInvoked.ContainsKey(spawnState))
58+
{
59+
m_SpawnStateInvoked.Add(spawnState, 1);
60+
}
61+
else
62+
{
63+
m_SpawnStateInvoked[spawnState]++;
64+
}
65+
}
66+
67+
private void RpcInvoked(RpcInvocations rpcInvocation)
68+
{
69+
if (!m_RpcInvocations.ContainsKey(rpcInvocation))
70+
{
71+
m_RpcInvocations.Add(rpcInvocation, 1);
72+
}
73+
else
74+
{
75+
m_RpcInvocations[rpcInvocation]++;
76+
}
77+
}
78+
79+
private void ValidateValues(int someIntValue, SerializableStruct someValues)
80+
{
81+
Assert.IsTrue(m_IntValue.Value == someIntValue);
82+
Assert.IsTrue(someValues.BoolValue == m_SerializableValue.Value.BoolValue);
83+
Assert.IsTrue(someValues.ULongValue == m_SerializableValue.Value.ULongValue);
84+
}
85+
86+
[Rpc(SendTo.Server)]
87+
private void SendToServerRpc(int someIntValue, SerializableStruct someValues, RpcParams rpcParams = default)
88+
{
89+
ValidateValues(someIntValue, someValues);
90+
RpcInvoked(RpcInvocations.SendToServerRpc);
91+
}
92+
93+
[Rpc(SendTo.Everyone)]
94+
private void SendToEveryoneRpc(int someIntValue, SerializableStruct someValues, RpcParams rpcParams = default)
95+
{
96+
ValidateValues(someIntValue, someValues);
97+
RpcInvoked(RpcInvocations.SendToEveryoneRpc);
98+
}
99+
100+
[Rpc(SendTo.Owner)]
101+
private void SendToOwnerRpc(int someIntValue, SerializableStruct someValues, RpcParams rpcParams = default)
102+
{
103+
ValidateValues(someIntValue, someValues);
104+
RpcInvoked(RpcInvocations.SendToOwnerRpc);
105+
}
106+
107+
108+
protected override void OnNetworkPreSpawn(ref NetworkManager networkManager)
109+
{
110+
SpawnStateInvoked(SpawnStates.PreSpawn);
111+
base.OnNetworkPreSpawn(ref networkManager);
112+
}
113+
114+
public override void OnNetworkSpawn()
115+
{
116+
SpawnStateInvoked(SpawnStates.Spawn);
117+
m_IntValue.Value = Random.Range(0, 100);
118+
m_SerializableValue.Value = new SerializableStruct()
119+
{
120+
BoolValue = Random.Range(0, 100) >= 50.0 ? true : false,
121+
ULongValue = (ulong)Random.Range(0, 100000),
122+
};
123+
base.OnNetworkSpawn();
124+
}
125+
126+
protected override void OnNetworkPostSpawn()
127+
{
128+
SpawnStateInvoked(SpawnStates.PostSpawn);
129+
SendToServerRpc(m_IntValue.Value, m_SerializableValue.Value);
130+
SendToEveryoneRpc(m_IntValue.Value, m_SerializableValue.Value);
131+
SendToOwnerRpc(m_IntValue.Value, m_SerializableValue.Value);
132+
base.OnNetworkPostSpawn();
133+
}
134+
135+
public void ValidateStatesAndRpcInvocations()
136+
{
137+
foreach (var entry in m_SpawnStateInvoked)
138+
{
139+
Assert.True(entry.Value == 1, $"{entry.Key} failed with {entry.Value} invocations!");
140+
}
141+
foreach (var entry in m_RpcInvocations)
142+
{
143+
Assert.True(entry.Value == 1, $"{entry.Key} failed with {entry.Value} invocations!");
144+
}
145+
}
146+
}
147+
148+
private GameObject m_PrefabToSpawn;
149+
private bool m_CanStartHost;
150+
151+
protected override IEnumerator OnSetup()
152+
{
153+
m_CanStartHost = false;
154+
return base.OnSetup();
155+
}
156+
157+
protected override void OnCreatePlayerPrefab()
158+
{
159+
m_PlayerPrefab.AddComponent<SinglePlayerTestComponent>();
160+
base.OnCreatePlayerPrefab();
161+
}
162+
163+
protected override void OnServerAndClientsCreated()
164+
{
165+
var singlePlayerTransport = m_ServerNetworkManager.gameObject.AddComponent<SinglePlayerTransport>();
166+
m_ServerNetworkManager.NetworkConfig.NetworkTransport = singlePlayerTransport;
167+
m_PrefabToSpawn = CreateNetworkObjectPrefab("TestObject");
168+
m_PrefabToSpawn.AddComponent<SinglePlayerTestComponent>();
169+
base.OnServerAndClientsCreated();
170+
}
171+
172+
protected override bool CanStartServerAndClients()
173+
{
174+
return m_CanStartHost;
175+
}
176+
177+
[UnityTest]
178+
public IEnumerator StartSinglePlayerAndSpawn()
179+
{
180+
m_CanStartHost = true;
181+
182+
yield return StartServerAndClients();
183+
184+
var spawnedInstance = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager).GetComponent<NetworkObject>();
185+
var testComponent = spawnedInstance.GetComponent<SinglePlayerTestComponent>();
186+
yield return s_DefaultWaitForTick;
187+
var playerTestComponent = m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent<SinglePlayerTestComponent>();
188+
testComponent.ValidateStatesAndRpcInvocations();
189+
playerTestComponent.ValidateStatesAndRpcInvocations();
190+
}
191+
192+
[UnityTest]
193+
public IEnumerator StartSinglePlayerAsClientError()
194+
{
195+
LogAssert.Expect(LogType.Error, $"[Netcode] {SinglePlayerTransport.NotStartingAsHostErrorMessage}");
196+
LogAssert.Expect(LogType.Error, $"[Netcode] Client is shutting down due to network transport start failure of {nameof(SinglePlayerTransport)}!");
197+
Assert.IsFalse(m_ServerNetworkManager.StartClient());
198+
yield return null;
199+
}
200+
201+
[UnityTest]
202+
public IEnumerator StartSinglePlayerAsServerError()
203+
{
204+
LogAssert.Expect(LogType.Error, $"[Netcode] {SinglePlayerTransport.NotStartingAsHostErrorMessage}");
205+
LogAssert.Expect(LogType.Error, $"[Netcode] Server is shutting down due to network transport start failure of {nameof(SinglePlayerTransport)}!");
206+
Assert.IsFalse(m_ServerNetworkManager.StartServer());
207+
yield return null;
208+
}
209+
}
210+
}

com.unity.netcode.gameobjects/Tests/Runtime/Transports/SinglePlayerTransportTests.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)