test: verify upstream and downstream connection stats end-to-end (#4508)

* test: verify upstream and downstream connection stats

Adds TestConnectionStats integration test where two clients connect,
each publishes audio + video, and the test asserts that both
publisher-side (LocalMediaTrack.GetTrackStats) and subscriber-side
(DownTrack.GetTrackStats) report non-zero packets and bytes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* sfu: add DownTrack.OnStatsUpdate hook and use it in stats test

Adds a public OnStatsUpdate setter on DownTrack mirroring the existing
pattern on WebRTCReceiver. The new callback fires alongside the
configured DownTrackListener (production path is unaffected) and is
intended for tests/observers to validate the AnalyticsStat data flowing
through the listener.

Augments TestConnectionStats to:
- hook WebRTCReceiver.OnStatsUpdate for each published track and assert
  the captured AnalyticsStat has non-zero packets/bytes (upstream).
- hook the new DownTrack.OnStatsUpdate for each subscribed track and
  make the same assertion (downstream).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Raja SubramanianandClaude Opus 4.7 authored and GitHub committed 2026-05-06 14:52:30 +05:30
1 parent c4fd71a5dd
commit 1ab1e072d1
2 files changed
+225

No files matched your search

+11
View File
@@ -385,6 +385,7 @@ type DownTrack struct {
blankFramesGeneration atomic.Uint32
connectionStats *connectionquality.ConnectionStats
onStatsUpdate atomic.Value // func(d *DownTrack, stat *livekit.AnalyticsStat)
isNACKThrottled atomic.Bool
@@ -471,6 +472,9 @@ func NewDownTrack(params DownTrackParams) (*DownTrack, error) {
})
d.connectionStats.OnStatsUpdate(func(_cs *connectionquality.ConnectionStats, stat *livekit.AnalyticsStat) {
d.params.Listener.OnStatsUpdate(stat)
if fn, ok := d.onStatsUpdate.Load().(func(*DownTrack, *livekit.AnalyticsStat)); ok && fn != nil {
fn(d, stat)
}
})
if d.kind == webrtc.RTPCodecTypeVideo {
@@ -2484,6 +2488,13 @@ func (d *DownTrack) GetConnectionScoreAndQuality() (float32, livekit.ConnectionQ
return d.connectionStats.GetScoreAndQuality()
}
// OnStatsUpdate registers an additional callback that fires alongside the
// configured DownTrackListener whenever connection-quality stats are produced.
// Intended for tests and observers; the production listener path is unaffected.
func (d *DownTrack) OnStatsUpdate(fn func(d *DownTrack, stat *livekit.AnalyticsStat)) {
d.onStatsUpdate.Store(fn)
}
func (d *DownTrack) GetTrackStats() *livekit.RTPStats {
return rtpstats.ReconcileRTPStatsWithRTX(d.rtpStats.ToProto(), d.rtpStatsRTX.ToProto())
}