@webex/plugin-meetings 2.60.1-next.7 → 2.60.1-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.d.ts +12 -2
- package/dist/constants.js +15 -5
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.d.ts +1 -1
- package/dist/locus-info/index.js +8 -8
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/index.d.ts +62 -18
- package/dist/meeting/index.js +679 -568
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +25 -18
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.d.ts +16 -0
- package/dist/meeting/util.js +71 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.d.ts +25 -3
- package/dist/meetings/index.js +83 -32
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +11 -6
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +3 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +50 -54
- package/dist/roap/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +1 -1
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +13 -10
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/constants.ts +13 -2
- package/src/locus-info/index.ts +13 -12
- package/src/meeting/index.ts +215 -116
- package/src/meeting/request.ts +7 -0
- package/src/meeting/util.ts +97 -0
- package/src/meetings/index.ts +59 -18
- package/src/reachability/index.ts +7 -4
- package/src/reconnection-manager/index.ts +1 -1
- package/src/roap/index.ts +49 -51
- package/src/statsAnalyzer/index.ts +2 -2
- package/src/statsAnalyzer/mqaUtil.ts +15 -14
- package/test/unit/spec/locus-info/index.js +53 -5
- package/test/unit/spec/meeting/index.js +1792 -1139
- package/test/unit/spec/meeting/request.js +22 -12
- package/test/unit/spec/meeting/utils.js +93 -0
- package/test/unit/spec/meetings/index.js +180 -21
- package/test/unit/spec/reachability/index.ts +2 -1
- package/test/unit/spec/reconnection-manager/index.js +1 -0
- package/test/unit/spec/roap/index.ts +28 -42
- package/test/unit/spec/stats-analyzer/index.js +415 -30
|
@@ -7,7 +7,9 @@ import {ConnectionState} from '@webex/internal-media-core';
|
|
|
7
7
|
import {StatsAnalyzer, EVENTS} from '../../../../src/statsAnalyzer';
|
|
8
8
|
import NetworkQualityMonitor from '../../../../src/networkQualityMonitor';
|
|
9
9
|
import testUtils from '../../../utils/testUtils';
|
|
10
|
-
import {MEDIA_DEVICES, _UNKNOWN_} from '@webex/plugin-meetings/src/constants';
|
|
10
|
+
import {MEDIA_DEVICES, MQA_INTERVAL, _UNKNOWN_} from '@webex/plugin-meetings/src/constants';
|
|
11
|
+
import LoggerProxy from '../../../../src/common/logs/logger-proxy';
|
|
12
|
+
import LoggerConfig from '../../../../src/common/logs/logger-config';
|
|
11
13
|
|
|
12
14
|
const {assert} = chai;
|
|
13
15
|
|
|
@@ -16,6 +18,156 @@ sinon.assert.expose(chai.assert, {prefix: ''});
|
|
|
16
18
|
|
|
17
19
|
describe('plugin-meetings', () => {
|
|
18
20
|
describe('StatsAnalyzer', () => {
|
|
21
|
+
describe('parseStatsResult', () => {
|
|
22
|
+
const sandbox = sinon.createSandbox();
|
|
23
|
+
let statsAnalyzer;
|
|
24
|
+
|
|
25
|
+
const initialConfig = {};
|
|
26
|
+
const defaultStats = {};
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
const networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
|
|
30
|
+
|
|
31
|
+
statsAnalyzer = new StatsAnalyzer(
|
|
32
|
+
initialConfig,
|
|
33
|
+
() => ({}),
|
|
34
|
+
networkQualityMonitor,
|
|
35
|
+
defaultStats
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
sandbox.reset();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should call processOutboundRTPResult', () => {
|
|
44
|
+
const calledSpy = sandbox.spy(statsAnalyzer, 'processOutboundRTPResult');
|
|
45
|
+
statsAnalyzer.parseGetStatsResult({ type: 'outbound-rtp' }, 'video-send');
|
|
46
|
+
assert(calledSpy.calledOnce);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should call processInboundRTPResult', () => {
|
|
50
|
+
const calledSpy = sandbox.spy(statsAnalyzer, 'processInboundRTPResult');
|
|
51
|
+
statsAnalyzer.parseGetStatsResult({ type: 'inbound-rtp' }, 'video-recv');
|
|
52
|
+
assert(calledSpy.calledOnce);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should call compareSentAndReceived', () => {
|
|
56
|
+
const calledSpy = sandbox.spy(statsAnalyzer, 'compareSentAndReceived');
|
|
57
|
+
statsAnalyzer.parseGetStatsResult({ type: 'remote-outbound-rtp' }, 'video-send');
|
|
58
|
+
assert(calledSpy.calledOnce);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should call parseCandidate', () => {
|
|
62
|
+
const calledSpy = sandbox.spy(statsAnalyzer, 'parseCandidate');
|
|
63
|
+
statsAnalyzer.parseGetStatsResult({ type: 'local-candidate' }, 'video-send');
|
|
64
|
+
assert(calledSpy.calledOnce);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('processOutboundRTPResult should create the correct stats results', () => {
|
|
68
|
+
// establish the `statsResults` object.
|
|
69
|
+
statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-send', true);
|
|
70
|
+
|
|
71
|
+
statsAnalyzer.processOutboundRTPResult({
|
|
72
|
+
bytesSent: 50000,
|
|
73
|
+
codecId: "RTCCodec_1_Outbound_111",
|
|
74
|
+
headerBytesSent: 25000,
|
|
75
|
+
id: "RTCOutboundRTPAudioStream_123456789",
|
|
76
|
+
kind: "audio",
|
|
77
|
+
mediaSourceId: "RTCAudioSource_2",
|
|
78
|
+
mediaType: "audio",
|
|
79
|
+
nackCount: 1,
|
|
80
|
+
packetsSent: 3600,
|
|
81
|
+
remoteId: "RTCRemoteInboundRtpAudioStream_123456789",
|
|
82
|
+
retransmittedBytesSent: 100,
|
|
83
|
+
retransmittedPacketsSent: 2,
|
|
84
|
+
ssrc: 123456789,
|
|
85
|
+
targetBitrate: 256000,
|
|
86
|
+
timestamp: 1707341489336,
|
|
87
|
+
trackId: "RTCMediaStreamTrack_sender_2",
|
|
88
|
+
transportId: "RTCTransport_0_1",
|
|
89
|
+
type: "outbound-rtp",
|
|
90
|
+
}, 'audio-send', true);
|
|
91
|
+
|
|
92
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.headerBytesSent, 25000);
|
|
93
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalBytesSent, 50000);
|
|
94
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalNackCount, 1);
|
|
95
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalPacketsSent, 3600)
|
|
96
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.retransmittedPacketsSent, 2);
|
|
97
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.retransmittedBytesSent, 100);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('processInboundRTPResult should create the correct stats results', () => {
|
|
101
|
+
// establish the `statsResults` object.
|
|
102
|
+
statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-recv-1', false);
|
|
103
|
+
|
|
104
|
+
statsAnalyzer.processInboundRTPResult({
|
|
105
|
+
audioLevel: 0,
|
|
106
|
+
bytesReceived: 509,
|
|
107
|
+
codecId: "RTCCodec_6_Inbound_111",
|
|
108
|
+
concealedSamples: 200000,
|
|
109
|
+
concealmentEvents: 13,
|
|
110
|
+
fecPacketsDiscarded: 1,
|
|
111
|
+
fecPacketsReceived: 1,
|
|
112
|
+
headerBytesReceived: 250,
|
|
113
|
+
id: "RTCInboundRTPAudioStream_123456789",
|
|
114
|
+
insertedSamplesForDeceleration: 0,
|
|
115
|
+
jitter: 0.012,
|
|
116
|
+
jitterBufferDelay: 1000,
|
|
117
|
+
jitterBufferEmittedCount: 10000,
|
|
118
|
+
kind: "audio",
|
|
119
|
+
lastPacketReceivedTimestamp: 1707341488529,
|
|
120
|
+
mediaType: "audio",
|
|
121
|
+
packetsDiscarded: 0,
|
|
122
|
+
packetsLost: 0,
|
|
123
|
+
packetsReceived: 12,
|
|
124
|
+
remoteId: "RTCRemoteOutboundRTPAudioStream_123456789",
|
|
125
|
+
removedSamplesForAcceleration: 0,
|
|
126
|
+
silentConcealedSamples: 200000,
|
|
127
|
+
ssrc: 123456789,
|
|
128
|
+
timestamp: 1707341489419,
|
|
129
|
+
totalAudioEnergy: 133,
|
|
130
|
+
totalSamplesDuration: 7,
|
|
131
|
+
totalSamplesReceived: 300000,
|
|
132
|
+
trackId: "RTCMediaStreamTrack_receiver_76",
|
|
133
|
+
transportId: "RTCTransport_0_1",
|
|
134
|
+
type: "inbound-rtp",
|
|
135
|
+
}, 'audio-recv-1', false);
|
|
136
|
+
|
|
137
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalPacketsReceived, 12);
|
|
138
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsDiscarded, 1);
|
|
139
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsReceived, 1);
|
|
140
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalBytesReceived, 509);
|
|
141
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.headerBytesReceived, 250);
|
|
142
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.audioLevel, 0);
|
|
143
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalAudioEnergy, 133);
|
|
144
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalSamplesReceived, 300000);
|
|
145
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalSamplesDecoded, 0);
|
|
146
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.concealedSamples, 200000);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('parseAudioSource should create the correct stats results', () => {
|
|
150
|
+
// establish the `statsResults` object.
|
|
151
|
+
statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-send', true);
|
|
152
|
+
|
|
153
|
+
statsAnalyzer.parseAudioSource({
|
|
154
|
+
audioLevel: 0.03,
|
|
155
|
+
echoReturnLoss: -30,
|
|
156
|
+
echoReturnLossEnhancement: 0.17,
|
|
157
|
+
id: "RTCAudioSource_2",
|
|
158
|
+
kind: "audio",
|
|
159
|
+
timestamp: 1707341488160.012,
|
|
160
|
+
totalAudioEnergy: 0.001,
|
|
161
|
+
totalSamplesDuration: 4.5,
|
|
162
|
+
trackIdentifier: "2207e5bf-c595-4301-93f7-283994d8143f",
|
|
163
|
+
type: "media-source",
|
|
164
|
+
}, 'audio-send', true);
|
|
165
|
+
|
|
166
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.audioLevel, 0.03);
|
|
167
|
+
assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalAudioEnergy, 0.001);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
19
171
|
describe('compareSentAndReceived()', () => {
|
|
20
172
|
let statsAnalyzer;
|
|
21
173
|
let sandBoxSpy;
|
|
@@ -91,6 +243,7 @@ describe('plugin-meetings', () => {
|
|
|
91
243
|
let networkQualityMonitor;
|
|
92
244
|
let statsAnalyzer;
|
|
93
245
|
let mqeData;
|
|
246
|
+
let loggerSpy;
|
|
94
247
|
|
|
95
248
|
let receivedEventsData = {
|
|
96
249
|
local: {},
|
|
@@ -103,6 +256,8 @@ describe('plugin-meetings', () => {
|
|
|
103
256
|
|
|
104
257
|
let fakeStats;
|
|
105
258
|
|
|
259
|
+
const sandbox = sinon.createSandbox();
|
|
260
|
+
|
|
106
261
|
const resetReceivedEvents = () => {
|
|
107
262
|
receivedEventsData = {
|
|
108
263
|
local: {},
|
|
@@ -110,6 +265,12 @@ describe('plugin-meetings', () => {
|
|
|
110
265
|
};
|
|
111
266
|
};
|
|
112
267
|
|
|
268
|
+
before(() => {
|
|
269
|
+
LoggerConfig.set({ enable: false });
|
|
270
|
+
LoggerProxy.set();
|
|
271
|
+
loggerSpy = sandbox.spy(LoggerProxy.logger, 'info');
|
|
272
|
+
});
|
|
273
|
+
|
|
113
274
|
beforeEach(() => {
|
|
114
275
|
clock = sinon.useFakeTimers();
|
|
115
276
|
|
|
@@ -124,8 +285,12 @@ describe('plugin-meetings', () => {
|
|
|
124
285
|
report: [
|
|
125
286
|
{
|
|
126
287
|
type: 'outbound-rtp',
|
|
127
|
-
packetsSent: 0,
|
|
128
288
|
bytesSent: 1,
|
|
289
|
+
packetsSent: 0,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
type: 'remote-inbound-rtp',
|
|
293
|
+
packetsLost: 0,
|
|
129
294
|
},
|
|
130
295
|
{
|
|
131
296
|
type: 'candidate-pair',
|
|
@@ -150,8 +315,14 @@ describe('plugin-meetings', () => {
|
|
|
150
315
|
report: [
|
|
151
316
|
{
|
|
152
317
|
type: 'inbound-rtp',
|
|
153
|
-
packetsReceived: 0,
|
|
154
318
|
bytesReceived: 1,
|
|
319
|
+
fecPacketsDiscarded: 0,
|
|
320
|
+
fecPacketsReceived: 0,
|
|
321
|
+
packetsLost: 0,
|
|
322
|
+
packetsReceived: 0,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
type: 'remote-outbound-rtp',
|
|
155
326
|
},
|
|
156
327
|
{
|
|
157
328
|
type: 'candidate-pair',
|
|
@@ -179,8 +350,13 @@ describe('plugin-meetings', () => {
|
|
|
179
350
|
report: [
|
|
180
351
|
{
|
|
181
352
|
type: 'outbound-rtp',
|
|
182
|
-
framesSent: 1500,
|
|
183
353
|
bytesSent: 1,
|
|
354
|
+
framesSent: 0,
|
|
355
|
+
packetsSent: 0,
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
type: 'remote-inbound-rtp',
|
|
359
|
+
packetsLost: 0,
|
|
184
360
|
},
|
|
185
361
|
{
|
|
186
362
|
type: 'candidate-pair',
|
|
@@ -205,11 +381,16 @@ describe('plugin-meetings', () => {
|
|
|
205
381
|
report: [
|
|
206
382
|
{
|
|
207
383
|
type: 'inbound-rtp',
|
|
208
|
-
framesDecoded: 0,
|
|
209
384
|
bytesReceived: 1,
|
|
210
385
|
frameHeight: 720,
|
|
211
386
|
frameWidth: 1280,
|
|
212
|
-
|
|
387
|
+
framesDecoded: 0,
|
|
388
|
+
framesReceived: 0,
|
|
389
|
+
packetsLost: 0,
|
|
390
|
+
packetsReceived: 0,
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
type: 'remote-outbound-rtp',
|
|
213
394
|
},
|
|
214
395
|
{
|
|
215
396
|
type: 'candidate-pair',
|
|
@@ -276,6 +457,7 @@ describe('plugin-meetings', () => {
|
|
|
276
457
|
});
|
|
277
458
|
|
|
278
459
|
afterEach(() => {
|
|
460
|
+
sandbox.reset();
|
|
279
461
|
clock.restore();
|
|
280
462
|
});
|
|
281
463
|
|
|
@@ -286,21 +468,27 @@ describe('plugin-meetings', () => {
|
|
|
286
468
|
await testUtils.flushPromises();
|
|
287
469
|
};
|
|
288
470
|
|
|
289
|
-
const mergeProperties = (
|
|
471
|
+
const mergeProperties = (
|
|
472
|
+
target,
|
|
473
|
+
properties,
|
|
474
|
+
keyValue = 'fake-candidate-id',
|
|
475
|
+
matchKey = 'type',
|
|
476
|
+
matchValue = 'local-candidate'
|
|
477
|
+
) => {
|
|
290
478
|
for (let key in target) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
479
|
+
if (target.hasOwnProperty(key)) {
|
|
480
|
+
if (typeof target[key] === 'object') {
|
|
481
|
+
mergeProperties(target[key], properties, keyValue, matchKey, matchValue);
|
|
482
|
+
}
|
|
483
|
+
if (key === 'id' && target[key] === keyValue && target[matchKey] === matchValue) {
|
|
484
|
+
Object.assign(target, properties);
|
|
298
485
|
}
|
|
486
|
+
}
|
|
299
487
|
}
|
|
300
|
-
|
|
488
|
+
};
|
|
301
489
|
|
|
302
|
-
const progressTime = async () => {
|
|
303
|
-
await clock.tickAsync(
|
|
490
|
+
const progressTime = async (time = initialConfig.analyzerInterval) => {
|
|
491
|
+
await clock.tickAsync(time);
|
|
304
492
|
await testUtils.flushPromises();
|
|
305
493
|
};
|
|
306
494
|
|
|
@@ -428,10 +616,10 @@ describe('plugin-meetings', () => {
|
|
|
428
616
|
});
|
|
429
617
|
|
|
430
618
|
it('emits the correct transportType in MEDIA_QUALITY events when using a TURN server', async () => {
|
|
431
|
-
fakeStats.audio.senders[0].report[
|
|
432
|
-
fakeStats.video.senders[0].report[
|
|
433
|
-
fakeStats.audio.receivers[0].report[
|
|
434
|
-
fakeStats.video.receivers[0].report[
|
|
619
|
+
fakeStats.audio.senders[0].report[4].relayProtocol = 'tls';
|
|
620
|
+
fakeStats.video.senders[0].report[4].relayProtocol = 'tls';
|
|
621
|
+
fakeStats.audio.receivers[0].report[4].relayProtocol = 'tls';
|
|
622
|
+
fakeStats.video.receivers[0].report[4].relayProtocol = 'tls';
|
|
435
623
|
|
|
436
624
|
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
437
625
|
|
|
@@ -478,14 +666,131 @@ describe('plugin-meetings', () => {
|
|
|
478
666
|
);
|
|
479
667
|
});
|
|
480
668
|
|
|
481
|
-
it('emits the correct
|
|
482
|
-
|
|
669
|
+
it('emits the correct transmittedFrameRate/receivedFrameRate', async () => {
|
|
670
|
+
it('at the start of the stats analyzer', async () => {
|
|
671
|
+
await startStatsAnalyzer();
|
|
672
|
+
assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.transmittedFrameRate, 0);
|
|
673
|
+
assert.strictEqual(mqeData.videoReceive[0].streams[0].common.receivedFrameRate, 0);
|
|
674
|
+
});
|
|
483
675
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
676
|
+
it('after frames are sent and received', async () => {
|
|
677
|
+
fakeStats.video.senders[0].report[0].framesSent += 300;
|
|
678
|
+
fakeStats.video.receivers[0].report[0].framesReceived += 300;
|
|
679
|
+
await progressTime(MQA_INTERVAL);
|
|
680
|
+
|
|
681
|
+
// 300 frames in 60 seconds = 5 frames per second
|
|
682
|
+
assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.transmittedFrameRate, 5);
|
|
683
|
+
assert.strictEqual(mqeData.videoReceive[0].streams[0].common.receivedFrameRate, 5);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
it('emits the correct rtpPackets', async () => {
|
|
688
|
+
it('at the start of the stats analyzer', async () => {
|
|
689
|
+
await startStatsAnalyzer();
|
|
690
|
+
assert.strictEqual(mqeData.audioTransmit[0].common.rtpPackets, 0);
|
|
691
|
+
assert.strictEqual(mqeData.audioTransmit[0].streams[0].common.rtpPackets, 0);
|
|
692
|
+
assert.strictEqual(mqeData.audioReceive[0].common.rtpPackets, 0);
|
|
693
|
+
assert.strictEqual(mqeData.audioReceive[0].streams[0].common.rtpPackets, 0);
|
|
694
|
+
assert.strictEqual(mqeData.videoTransmit[0].common.rtpPackets, 0);
|
|
695
|
+
assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.rtpPackets, 0);
|
|
696
|
+
assert.strictEqual(mqeData.videoReceive[0].common.rtpPackets, 0);
|
|
697
|
+
assert.strictEqual(mqeData.videoReceive[0].streams[0].common.rtpPackets, 0);
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
it('after packets are sent', async () => {
|
|
701
|
+
fakeStats.audio.senders[0].report[0].packetsSent += 5;
|
|
702
|
+
fakeStats.video.senders[0].report[0].packetsSent += 5;
|
|
703
|
+
await progressTime(MQA_INTERVAL);
|
|
704
|
+
|
|
705
|
+
assert.strictEqual(mqeData.audioTransmit[0].common.rtpPackets, 5);
|
|
706
|
+
assert.strictEqual(mqeData.audioTransmit[0].streams[0].common.rtpPackets, 5);
|
|
707
|
+
assert.strictEqual(mqeData.videoTransmit[0].common.rtpPackets, 5);
|
|
708
|
+
assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.rtpPackets, 5);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it('after packets are received', async () => {
|
|
712
|
+
fakeStats.audio.senders[0].report[0].packetsSent += 10;
|
|
713
|
+
fakeStats.video.senders[0].report[0].packetsSent += 10;
|
|
714
|
+
fakeStats.audio.receivers[0].report[0].packetsReceived += 10;
|
|
715
|
+
fakeStats.video.receivers[0].report[0].packetsReceived += 10;
|
|
716
|
+
await progressTime(MQA_INTERVAL);
|
|
717
|
+
|
|
718
|
+
assert.strictEqual(mqeData.audioReceive[0].common.rtpPackets, 10);
|
|
719
|
+
assert.strictEqual(mqeData.audioReceive[0].streams[0].common.rtpPackets, 10);
|
|
720
|
+
assert.strictEqual(mqeData.videoReceive[0].common.rtpPackets, 10);
|
|
721
|
+
assert.strictEqual(mqeData.videoReceive[0].streams[0].common.rtpPackets, 10);
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
it('emits the correct fecPackets', async () => {
|
|
726
|
+
it('at the start of the stats analyzer', async () => {
|
|
727
|
+
await startStatsAnalyzer();
|
|
728
|
+
assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 0);
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
it('after FEC packets are received', async () => {
|
|
732
|
+
fakeStats.audio.receivers[0].report[0].fecPacketsReceived += 5;
|
|
733
|
+
await progressTime(MQA_INTERVAL);
|
|
734
|
+
|
|
735
|
+
assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 5);
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
it('after FEC packets are received and some FEC packets are discarded', async () => {
|
|
739
|
+
fakeStats.audio.receivers[0].report[0].fecPacketsReceived += 15;
|
|
740
|
+
fakeStats.audio.receivers[0].report[0].fecPacketsDiscarded += 5;
|
|
741
|
+
await progressTime(MQA_INTERVAL);
|
|
742
|
+
|
|
743
|
+
assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 10);
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it('emits the correct mediaHopByHopLost/rtpHopByHopLost', async () => {
|
|
748
|
+
it('at the start of the stats analyzer', async () => {
|
|
749
|
+
await startStatsAnalyzer();
|
|
750
|
+
assert.strictEqual(mqeData.audioReceive[0].common.mediaHopByHopLost, 0);
|
|
751
|
+
assert.strictEqual(mqeData.audioReceive[0].common.rtpHopByHopLost, 0);
|
|
752
|
+
assert.strictEqual(mqeData.videoReceive[0].common.mediaHopByHopLost, 0);
|
|
753
|
+
assert.strictEqual(mqeData.videoReceive[0].common.rtpHopByHopLost, 0);
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
it('after packets are lost', async () => {
|
|
757
|
+
fakeStats.audio.receivers[0].report[0].packetsLost += 5;
|
|
758
|
+
fakeStats.video.receivers[0].report[0].packetsLost += 5;
|
|
759
|
+
await progressTime(MQA_INTERVAL);
|
|
760
|
+
|
|
761
|
+
assert.strictEqual(mqeData.audioReceive[0].common.mediaHopByHopLost, 5);
|
|
762
|
+
assert.strictEqual(mqeData.audioReceive[0].common.rtpHopByHopLost, 5);
|
|
763
|
+
assert.strictEqual(mqeData.videoReceive[0].common.mediaHopByHopLost, 5);
|
|
764
|
+
assert.strictEqual(mqeData.videoReceive[0].common.rtpHopByHopLost, 5);
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
it('emits the correct remoteLossRate', async () => {
|
|
769
|
+
it('at the start of the stats analyzer', async () => {
|
|
770
|
+
await startStatsAnalyzer();
|
|
771
|
+
assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 0);
|
|
772
|
+
assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 0);
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
it('after packets are sent', async () => {
|
|
776
|
+
fakeStats.audio.senders[0].report[0].packetsSent += 100;
|
|
777
|
+
fakeStats.video.senders[0].report[0].packetsSent += 100;
|
|
778
|
+
await progressTime(MQA_INTERVAL);
|
|
779
|
+
|
|
780
|
+
assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 0);
|
|
781
|
+
assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 0);
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
it('after packets are sent and some packets are lost', async () => {
|
|
785
|
+
fakeStats.audio.senders[0].report[0].packetsSent += 200;
|
|
786
|
+
fakeStats.audio.senders[0].report[1].packetsLost += 10;
|
|
787
|
+
fakeStats.video.senders[0].report[0].packetsSent += 200;
|
|
788
|
+
fakeStats.video.senders[0].report[1].packetsLost += 10;
|
|
789
|
+
await progressTime(MQA_INTERVAL);
|
|
790
|
+
|
|
791
|
+
assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 5);
|
|
792
|
+
assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 5);
|
|
793
|
+
});
|
|
489
794
|
});
|
|
490
795
|
|
|
491
796
|
it('has the correct localIpAddress set when the candidateType is host', async () => {
|
|
@@ -503,7 +808,11 @@ describe('plugin-meetings', () => {
|
|
|
503
808
|
|
|
504
809
|
await progressTime();
|
|
505
810
|
assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
|
|
506
|
-
mergeProperties(fakeStats, {
|
|
811
|
+
mergeProperties(fakeStats, {
|
|
812
|
+
relayProtocol: 'test',
|
|
813
|
+
address: 'test2',
|
|
814
|
+
candidateType: 'prflx',
|
|
815
|
+
});
|
|
507
816
|
await progressTime();
|
|
508
817
|
assert.strictEqual(statsAnalyzer.getLocalIpAddress(), 'test2');
|
|
509
818
|
});
|
|
@@ -513,7 +822,11 @@ describe('plugin-meetings', () => {
|
|
|
513
822
|
|
|
514
823
|
await progressTime();
|
|
515
824
|
assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
|
|
516
|
-
mergeProperties(fakeStats, {
|
|
825
|
+
mergeProperties(fakeStats, {
|
|
826
|
+
relatedAddress: 'relatedAddress',
|
|
827
|
+
address: 'test2',
|
|
828
|
+
candidateType: 'prflx',
|
|
829
|
+
});
|
|
517
830
|
await progressTime();
|
|
518
831
|
assert.strictEqual(statsAnalyzer.getLocalIpAddress(), 'relatedAddress');
|
|
519
832
|
});
|
|
@@ -527,6 +840,78 @@ describe('plugin-meetings', () => {
|
|
|
527
840
|
await progressTime();
|
|
528
841
|
assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
|
|
529
842
|
});
|
|
843
|
+
|
|
844
|
+
it('logs a message when audio send packets do not increase', async () => {
|
|
845
|
+
await startStatsAnalyzer({expected: {sendAudio: true}});
|
|
846
|
+
|
|
847
|
+
// don't increase the packets when time progresses.
|
|
848
|
+
await progressTime();
|
|
849
|
+
|
|
850
|
+
assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent'));
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
it('does not log a message when audio send packets increase', async () => {
|
|
854
|
+
await startStatsAnalyzer({expected: {sendAudio: true}});
|
|
855
|
+
|
|
856
|
+
fakeStats.audio.senders[0].report[0].packetsSent += 5;
|
|
857
|
+
await progressTime();
|
|
858
|
+
|
|
859
|
+
assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent'));
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
it('logs a message when audio receive packets do not increase', async () => {
|
|
863
|
+
await startStatsAnalyzer({expected: {receiveAudio: true}});
|
|
864
|
+
|
|
865
|
+
// don't increase the packets when time progresses.
|
|
866
|
+
await progressTime();
|
|
867
|
+
|
|
868
|
+
assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
it('does not log a message when audio receive packets increase', async () => {
|
|
872
|
+
await startStatsAnalyzer({expected: {receiveAudio: true}});
|
|
873
|
+
|
|
874
|
+
fakeStats.audio.receivers[0].report[0].packetsReceived += 5;
|
|
875
|
+
await progressTime();
|
|
876
|
+
|
|
877
|
+
assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
it('logs a message when video send packets do not increase', async () => {
|
|
881
|
+
await startStatsAnalyzer({expected: {sendVideo: true}});
|
|
882
|
+
|
|
883
|
+
// don't increase the packets when time progresses.
|
|
884
|
+
await progressTime();
|
|
885
|
+
|
|
886
|
+
assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent'));
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
it('does not log a message when video send packets increase', async () => {
|
|
890
|
+
await startStatsAnalyzer({expected: {sendVideo: true}});
|
|
891
|
+
|
|
892
|
+
fakeStats.video.senders[0].report[0].packetsSent += 5;
|
|
893
|
+
await progressTime();
|
|
894
|
+
|
|
895
|
+
assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent'));
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
it('logs a message when video receive packets do not increase', async () => {
|
|
899
|
+
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
900
|
+
|
|
901
|
+
// don't increase the packets when time progresses.
|
|
902
|
+
await progressTime();
|
|
903
|
+
|
|
904
|
+
assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received'));
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it('does not log a message when video receive packets increase', async () => {
|
|
908
|
+
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
909
|
+
|
|
910
|
+
fakeStats.video.receivers[0].report[0].packetsReceived += 5;
|
|
911
|
+
await progressTime();
|
|
912
|
+
|
|
913
|
+
assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
|
|
914
|
+
});
|
|
530
915
|
});
|
|
531
916
|
});
|
|
532
917
|
});
|