Skip to content

Commit 0376479

Browse files
MaxHeimbrockclaude
andcommitted
Add PlayMode tests for PublishData size limits
LocalParticipant.PublishData is fire-and-forget — the C# API has no callback, so server-side drops of oversized packets are silent. These tests probe the boundary empirically by publishing payloads of varying sizes between two participants and asserting delivery via the subscriber's DataReceived event. Retries on a 200 ms interval to avoid SFU warm-up flakiness. Verified against livekit-server 1.12.0: 1 KiB and 15 KiB arrive intact (length + bytes); 65 KiB is dropped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a7a1f33 commit 0376479

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

Tests/PlayMode/PublishDataTests.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System.Collections;
2+
using NUnit.Framework;
3+
using UnityEngine;
4+
using UnityEngine.TestTools;
5+
using LiveKit.PlayModeTests.Utils;
6+
7+
namespace LiveKit.PlayModeTests
8+
{
9+
// Probes the server-side size limit on LocalParticipant.PublishData. The C# API is
10+
// fire-and-forget (no callback), so the only observable signal is whether the
11+
// subscriber's DataReceived event fires within a timeout. The SFU data path may
12+
// not be ready immediately after connect, so we retry publishing on an interval.
13+
public class PublishDataTests
14+
{
15+
[UnityTest, Category("E2E")]
16+
public IEnumerator Small_1KiB_Arrives()
17+
{
18+
yield return RunSizeProbe(1024, shouldArrive: true);
19+
}
20+
21+
[UnityTest, Category("E2E")]
22+
public IEnumerator At_15KiB_Arrives()
23+
{
24+
yield return RunSizeProbe(15 * 1024, shouldArrive: true);
25+
}
26+
27+
[UnityTest, Category("E2E")]
28+
public IEnumerator Above_64KiB_DoesNotArrive()
29+
{
30+
yield return RunSizeProbe(65 * 1024, shouldArrive: false);
31+
}
32+
33+
private static IEnumerator RunSizeProbe(int payloadBytes, bool shouldArrive)
34+
{
35+
var publisher = TestRoomContext.ConnectionOptions.Default;
36+
publisher.Identity = "publisher";
37+
var subscriber = TestRoomContext.ConnectionOptions.Default;
38+
subscriber.Identity = "subscriber";
39+
40+
using var context = new TestRoomContext(new[] { publisher, subscriber });
41+
yield return context.ConnectAll();
42+
Assert.IsNull(context.ConnectionError);
43+
44+
var publisherRoom = context.Rooms[0];
45+
var subscriberRoom = context.Rooms[1];
46+
47+
var payload = new byte[payloadBytes];
48+
for (int i = 0; i < payloadBytes; i++) payload[i] = (byte)(i & 0xFF);
49+
50+
byte[] received = null;
51+
subscriberRoom.DataReceived += (data, participant, kind, topic) =>
52+
{
53+
if (received == null) received = data;
54+
};
55+
56+
float timeout = shouldArrive ? 5f : 3f;
57+
float start = Time.realtimeSinceStartup;
58+
float lastPublish = -1f;
59+
const float interval = 0.2f;
60+
while (received == null && Time.realtimeSinceStartup - start < timeout)
61+
{
62+
if (Time.realtimeSinceStartup - lastPublish >= interval)
63+
{
64+
publisherRoom.LocalParticipant.PublishData(payload);
65+
lastPublish = Time.realtimeSinceStartup;
66+
}
67+
yield return null;
68+
}
69+
70+
if (shouldArrive)
71+
{
72+
Assert.IsNotNull(received,
73+
$"Expected {payloadBytes}-byte payload to arrive within {timeout}s");
74+
Assert.AreEqual(payloadBytes, received.Length, "Received payload length mismatch");
75+
CollectionAssert.AreEqual(payload, received, "Received payload contents mismatch");
76+
}
77+
else
78+
{
79+
Assert.IsNull(received,
80+
$"Expected {payloadBytes}-byte payload to be dropped, but it arrived ({received?.Length} bytes)");
81+
}
82+
}
83+
}
84+
}

Tests/PlayMode/PublishDataTests.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)