Skip to content

Commit 77766fa

Browse files
authored
feat: Add test for named message sent and named message received metrics (#861)
* Add test for named message sent * Add test for named messages sent to multiple clients * Add test for named message received * Revert editor changes * Code review fixes * Merge test fixes
1 parent 103cd52 commit 77766fa

File tree

6 files changed

+223
-19
lines changed

6 files changed

+223
-19
lines changed

com.unity.multiplayer.mlapi/Runtime/Metrics/NetworkMetrics.cs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using MLAPI.Connection;
32
using Unity.Multiplayer.NetStats.Dispatch;
43
using Unity.Multiplayer.NetStats.Metrics;
54
using Unity.Multiplayer.NetworkProfiler;
@@ -11,11 +10,11 @@ public interface INetworkMetrics
1110
{
1211
void TrackNetworkObject(NetworkObject networkObject);
1312

14-
void TrackNamedMessageSent(ulong receiver, string messageName, ulong bytesCount);
13+
void TrackNamedMessageSent(ulong receiverClientId, string messageName, ulong bytesCount);
1514

16-
void TrackNamedMessageSent(IReadOnlyCollection<ulong> receivers, string messageName, ulong bytesCount);
15+
void TrackNamedMessageSent(IReadOnlyCollection<ulong> receiverClientIds, string messageName, ulong bytesCount);
1716

18-
void TrackNamedMessageReceived(ulong sender, string messageName, ulong bytesCount);
17+
void TrackNamedMessageReceived(ulong senderClientId, string messageName, ulong bytesCount);
1918

2019
void DispatchFrame();
2120
}
@@ -26,15 +25,15 @@ public void TrackNetworkObject(NetworkObject networkObject)
2625
{
2726
}
2827

29-
public void TrackNamedMessageSent(ulong receiver, string messageName, ulong bytesCount)
28+
public void TrackNamedMessageSent(ulong receiverClientId, string messageName, ulong bytesCount)
3029
{
3130
}
3231

33-
public void TrackNamedMessageSent(IReadOnlyCollection<ulong> receivers, string messageName, ulong bytesCount)
32+
public void TrackNamedMessageSent(IReadOnlyCollection<ulong> receiverClientIds, string messageName, ulong bytesCount)
3433
{
3534
}
3635

37-
public void TrackNamedMessageReceived(ulong sender, string messageName, ulong bytesCount)
36+
public void TrackNamedMessageReceived(ulong senderClientId, string messageName, ulong bytesCount)
3837
{
3938
}
4039

@@ -46,7 +45,6 @@ public void DispatchFrame()
4645
#if true
4746
public class NetworkMetrics : INetworkMetrics
4847
{
49-
private readonly IMetricDispatcher m_Dispatcher;
5048
private readonly NetworkManager m_NetworkManager;
5149

5250
private EventMetric<NamedMessageEvent> m_NamedMessageSentEvent = new EventMetric<NamedMessageEvent>("Named Message Sent");
@@ -57,13 +55,15 @@ public class NetworkMetrics : INetworkMetrics
5755
public NetworkMetrics(NetworkManager networkManager)
5856
{
5957
m_NetworkManager = networkManager;
60-
m_Dispatcher = new MetricDispatcherBuilder()
58+
Dispatcher = new MetricDispatcherBuilder()
6159
.WithMetricEvents(m_NamedMessageSentEvent, m_NamedMessageReceivedEvent)
6260
.Build();
63-
64-
m_Dispatcher.RegisterObserver(MLAPIObserver.Observer);
61+
62+
Dispatcher.RegisterObserver(MLAPIObserver.Observer);
6563
}
6664

65+
internal IMetricDispatcher Dispatcher { get; }
66+
6767
public void TrackNetworkObject(NetworkObject networkObject)
6868
{
6969
if (!m_NetworkGameObjects.ContainsKey(networkObject.NetworkObjectId))
@@ -72,27 +72,27 @@ public void TrackNetworkObject(NetworkObject networkObject)
7272
}
7373
}
7474

75-
public void TrackNamedMessageSent(ulong receiver, string messageName, ulong bytesCount)
75+
public void TrackNamedMessageSent(ulong receiverClientId, string messageName, ulong bytesCount)
7676
{
77-
m_NamedMessageSentEvent.Mark(new NamedMessageEvent(new ConnectionInfo(receiver), messageName, bytesCount));
77+
m_NamedMessageSentEvent.Mark(new NamedMessageEvent(new ConnectionInfo(receiverClientId), messageName, bytesCount));
7878
}
7979

80-
public void TrackNamedMessageSent(IReadOnlyCollection<ulong> receivers, string messageName, ulong bytesCount)
80+
public void TrackNamedMessageSent(IReadOnlyCollection<ulong> receiverClientIds, string messageName, ulong bytesCount)
8181
{
82-
foreach (var receiver in receivers)
82+
foreach (var receiver in receiverClientIds)
8383
{
8484
TrackNamedMessageSent(receiver, messageName, bytesCount);
8585
}
8686
}
8787

88-
public void TrackNamedMessageReceived(ulong sender, string messageName, ulong bytesCount)
88+
public void TrackNamedMessageReceived(ulong senderClientId, string messageName, ulong bytesCount)
8989
{
90-
m_NamedMessageReceivedEvent.Mark(new NamedMessageEvent(new ConnectionInfo(sender), messageName, bytesCount));
90+
m_NamedMessageReceivedEvent.Mark(new NamedMessageEvent(new ConnectionInfo(senderClientId), messageName, bytesCount));
9191
}
9292

9393
public void DispatchFrame()
9494
{
95-
m_Dispatcher.Dispatch();
95+
Dispatcher.Dispatch();
9696
}
9797
}
9898

com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ internal void SpawnNetworkObjectLocally(NetworkObject networkObject, ulong netwo
302302
SpawnedObjects.Add(networkObject.NetworkObjectId, networkObject);
303303
SpawnedObjectsList.Add(networkObject);
304304

305-
NetworkManager.Singleton.NetworkMetrics.TrackNetworkObject(networkObject);
305+
NetworkManager.NetworkMetrics.TrackNetworkObject(networkObject);
306306

307307
if (ownerClientId != null)
308308
{

com.unity.multiplayer.mlapi/Tests/Runtime/Metrics.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
using MLAPI.Metrics;
7+
using NUnit.Framework;
8+
using Unity.Multiplayer.NetStats.Dispatch;
9+
using Unity.Multiplayer.NetStats.Metrics;
10+
using Unity.Multiplayer.NetworkProfiler;
11+
using Unity.Multiplayer.NetworkProfiler.Models;
12+
using UnityEngine;
13+
using UnityEngine.TestTools;
14+
15+
namespace MLAPI.RuntimeTests.Metrics
16+
{
17+
#if true
18+
public class NetworkMetricsTests
19+
{
20+
[UnityTest]
21+
public IEnumerator NetworkMetrics_WhenNamedMessageSent_TracksNamedMessageSentMetric()
22+
{
23+
NetworkManagerHelper.StartNetworkManager(out var networkManager);
24+
var networkMetrics = networkManager.NetworkMetrics as NetworkMetrics;
25+
var messageName = Guid.NewGuid().ToString();
26+
27+
var clientId = 100UL;
28+
networkMetrics.Dispatcher.RegisterObserver(new TestObserver(collection =>
29+
{
30+
var namedMessageSentMetric = AssertSingleMetricEventOfType<NamedMessageEvent>(collection, MetricNames.NamedMessageSent);
31+
Assert.AreEqual(1, namedMessageSentMetric.Values.Count);
32+
33+
var namedMessageSent = namedMessageSentMetric.Values.First();
34+
Assert.AreEqual(messageName, namedMessageSent.Name);
35+
Assert.AreEqual(clientId, namedMessageSent.Connection.Id);
36+
}));
37+
38+
networkManager.CustomMessagingManager.SendNamedMessage(messageName, clientId, Stream.Null);
39+
40+
yield return WaitForMetricsDispatch();
41+
42+
NetworkManagerHelper.ShutdownNetworkManager();
43+
}
44+
45+
[UnityTest]
46+
public IEnumerator NetworkMetrics_WhenNamedMessageSentToMultipleClients_TracksNamedMessageSentMetric()
47+
{
48+
NetworkManagerHelper.StartNetworkManager(out var networkManager);
49+
var networkMetrics = networkManager.NetworkMetrics as NetworkMetrics;
50+
var messageName = Guid.NewGuid().ToString();
51+
52+
networkMetrics.Dispatcher.RegisterObserver(new TestObserver(collection =>
53+
{
54+
var namedMessageSentMetric = AssertSingleMetricEventOfType<NamedMessageEvent>(collection, MetricNames.NamedMessageSent);
55+
Assert.AreEqual(3, namedMessageSentMetric.Values.Count);
56+
57+
var clientIds = namedMessageSentMetric.Values.Select(x => x.Connection.Id).ToList();
58+
Assert.Contains(100UL, clientIds);
59+
Assert.Contains(200UL, clientIds);
60+
Assert.Contains(300UL, clientIds);
61+
}));
62+
63+
networkManager.CustomMessagingManager.SendNamedMessage(messageName, new List<ulong> { 100, 200, 300 }, Stream.Null);
64+
65+
yield return WaitForMetricsDispatch();
66+
67+
NetworkManagerHelper.ShutdownNetworkManager();
68+
}
69+
70+
[UnityTest]
71+
public IEnumerator NetworkMetrics_WhenNamedMessageReceived_TracksNamedMessageReceivedMetric()
72+
{
73+
var createServerAndSingleClient = new CreateServerAndSingleClient();
74+
yield return createServerAndSingleClient.Run();
75+
var server = createServerAndSingleClient.Server;
76+
var client = createServerAndSingleClient.Client;
77+
var clientMetrics = client.NetworkMetrics as NetworkMetrics;
78+
79+
var messageName = Guid.NewGuid().ToString();
80+
LogAssert.Expect(LogType.Log, $"Received from {server.LocalClientId}");
81+
client.CustomMessagingManager.RegisterNamedMessageHandler(messageName, (sender, payload) =>
82+
{
83+
Debug.Log($"Received from {sender}");
84+
});
85+
86+
var found = false;
87+
clientMetrics.Dispatcher.RegisterObserver(new TestObserver(collection =>
88+
{
89+
var namedMessageSentMetric = collection.Metrics.SingleOrDefault(x => x.Name == MetricNames.NamedMessageReceived);
90+
Assert.NotNull(namedMessageSentMetric);
91+
92+
var typedMetric = namedMessageSentMetric as IEventMetric<NamedMessageEvent>;
93+
Assert.NotNull(typedMetric);
94+
if (typedMetric.Values.Any()) // We always get the metric, but when it has values, something has been tracked
95+
{
96+
Assert.AreEqual(1, typedMetric.Values.Count);
97+
98+
var namedMessageSent = typedMetric.Values.First();
99+
Assert.AreEqual(messageName, namedMessageSent.Name);
100+
Assert.AreEqual(server.LocalClientId, namedMessageSent.Connection.Id);
101+
102+
found = true;
103+
}
104+
}));
105+
106+
server.CustomMessagingManager.SendNamedMessage(messageName, client.LocalClientId, Stream.Null);
107+
108+
yield return WaitForAFewFrames(); // Client does not receive message synchronously
109+
110+
MultiInstanceHelpers.Destroy();
111+
112+
Assert.True(found);
113+
}
114+
115+
private IEnumerator WaitForMetricsDispatch()
116+
{
117+
yield return new WaitForEndOfFrame();
118+
yield return new WaitForEndOfFrame();
119+
}
120+
121+
private IEnumerator WaitForAFewFrames()
122+
{
123+
yield return new WaitForSeconds(0.5f);
124+
}
125+
126+
private IEventMetric<TEvent> AssertSingleMetricEventOfType<TEvent>(MetricCollection collection, string name)
127+
{
128+
var metric = collection.Metrics.SingleOrDefault(x => x.Name == name);
129+
Assert.NotNull(metric);
130+
131+
var typedMetric = metric as IEventMetric<TEvent>;
132+
Assert.NotNull(typedMetric);
133+
Assert.IsNotEmpty(typedMetric.Values);
134+
135+
return typedMetric;
136+
}
137+
138+
private class TestObserver : IMetricObserver
139+
{
140+
private readonly Action<MetricCollection> m_Assertion;
141+
142+
public TestObserver(Action<MetricCollection> assertion)
143+
{
144+
m_Assertion = assertion;
145+
}
146+
147+
public void Observe(MetricCollection collection)
148+
{
149+
m_Assertion.Invoke(collection);
150+
}
151+
}
152+
153+
public class CreateServerAndSingleClient
154+
{
155+
public NetworkManager Server { get; private set; }
156+
157+
public NetworkManager Client { get; private set; }
158+
159+
public IEnumerator Run()
160+
{
161+
if (!MultiInstanceHelpers.Create(1, out var server, out NetworkManager[] clients))
162+
{
163+
Debug.LogError("Failed to create instances");
164+
Assert.Fail("Failed to create instances");
165+
}
166+
167+
if (!MultiInstanceHelpers.Start(true, server, clients))
168+
{
169+
Debug.LogError("Failed to start instances");
170+
Assert.Fail("Failed to start instances");
171+
}
172+
173+
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
174+
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientConnectedToServer(server));
175+
176+
Server = server;
177+
Client = clients.SingleOrDefault();
178+
}
179+
}
180+
}
181+
#endif
182+
}

com.unity.multiplayer.mlapi/Tests/Runtime/Metrics/NetworkMetricsTests.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.

com.unity.multiplayer.mlapi/Tests/Runtime/com.unity.multiplayer.mlapi.runtimetests.asmdef

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{
22
"name": "Unity.Multiplayer.MLAPI.RuntimeTests",
3+
"rootNamespace": "",
34
"references": [
45
"Unity.Multiplayer.MLAPI.Runtime",
6+
"Unity.Multiplayer.NetworkProfiler.Runtime",
7+
"Unity.Multiplayer.NetStats",
58
"Unity.Multiplayer.MLAPI.Editor"
69
],
710
"optionalUnityReferences": [

0 commit comments

Comments
 (0)