(t *testing.T)
| 245 | } |
| 246 | |
| 247 | func TestConnectionStats(t *testing.T) { |
| 248 | if testing.Short() { |
| 249 | t.SkipNow() |
| 250 | return |
| 251 | } |
| 252 | |
| 253 | s, finish := setupSingleNodeTest("TestConnectionStats") |
| 254 | defer finish() |
| 255 | |
| 256 | for _, testRTCServicePath := range testRTCServicePaths { |
| 257 | t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) { |
| 258 | c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil) |
| 259 | c2 := createRTCClient("c2", defaultServerPort, testRTCServicePath, nil) |
| 260 | waitUntilConnected(t, c1, c2) |
| 261 | defer func() { |
| 262 | c1.Stop() |
| 263 | c2.Stop() |
| 264 | }() |
| 265 | |
| 266 | // both clients publish audio + video |
| 267 | t1, err := c1.AddStaticTrack("audio/opus", "audio", "c1audio") |
| 268 | require.NoError(t, err) |
| 269 | defer t1.Stop() |
| 270 | t2, err := c1.AddStaticTrack("video/vp8", "video", "c1video") |
| 271 | require.NoError(t, err) |
| 272 | defer t2.Stop() |
| 273 | |
| 274 | t3, err := c2.AddStaticTrack("audio/opus", "audio", "c2audio") |
| 275 | require.NoError(t, err) |
| 276 | defer t3.Stop() |
| 277 | t4, err := c2.AddStaticTrack("video/vp8", "video", "c2video") |
| 278 | require.NoError(t, err) |
| 279 | defer t4.Stop() |
| 280 | |
| 281 | // wait for cross-subscriptions: each client should receive 2 tracks from the other |
| 282 | testutils.WithTimeout(t, func() string { |
| 283 | if len(c1.SubscribedTracks()[c2.ID()]) != 2 { |
| 284 | return "c1 did not subscribe to both tracks from c2" |
| 285 | } |
| 286 | if len(c2.SubscribedTracks()[c1.ID()]) != 2 { |
| 287 | return "c2 did not subscribe to both tracks from c1" |
| 288 | } |
| 289 | return "" |
| 290 | }) |
| 291 | |
| 292 | room := s.RoomManager().GetRoom(context.Background(), testRoom) |
| 293 | require.NotNil(t, room) |
| 294 | |
| 295 | // hook the upstream WebRTCReceiver.OnStatsUpdate and downstream DownTrack.OnStatsUpdate |
| 296 | // callbacks so we can verify the AnalyticsStat delivered through each carries valid |
| 297 | // delta data. MediaTrack.Receivers() returns one entry per potential codec; only those |
| 298 | // matching the actually published codec are *sfu.WebRTCReceiver, the rest are |
| 299 | // placeholder *rtc.DummyReceiver instances that we skip. |
| 300 | type statCapture struct { |
| 301 | lock sync.Mutex |
| 302 | stat *livekit.AnalyticsStat |
| 303 | } |
| 304 | receiverCaptures := make(map[livekit.TrackID]*statCapture) |
nothing calls this directly
no test coverage detected