@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391
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 +58 -8
- package/dist/annotation/annotation.types.js +7 -0
- package/dist/annotation/annotation.types.js.map +1 -0
- package/dist/annotation/constants.js +49 -0
- package/dist/annotation/constants.js.map +1 -0
- package/dist/annotation/index.js +342 -0
- package/dist/annotation/index.js.map +1 -0
- package/dist/breakouts/breakout.js +94 -15
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +671 -81
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/utils.js +45 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- package/dist/common/errors/reclaim-host-role-errors.js +158 -0
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
- package/dist/common/errors/webex-errors.js +48 -7
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +5 -1
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +24 -9
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +5 -10
- package/dist/config.js.map +1 -1
- package/dist/constants.js +242 -33
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +14 -2
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +109 -15
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js +7 -0
- package/dist/controls-options-manager/types.js.map +1 -0
- package/dist/controls-options-manager/util.js +309 -18
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +110 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.js +93 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +380 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/siLanguage.js +25 -0
- package/dist/interpretation/siLanguage.js.map +1 -0
- package/dist/locus-info/controlsUtils.js +91 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +386 -62
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +7 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +71 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +249 -72
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +89 -14
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +65 -102
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +73 -124
- package/dist/media/properties.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +135 -330
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +86 -2
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +4075 -2827
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +292 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +224 -136
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +177 -152
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +672 -417
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +73 -7
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +192 -51
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/util.js +1 -1
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +36 -36
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +39 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +484 -119
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +7 -0
- package/dist/meetings/meetings.types.js.map +1 -0
- package/dist/meetings/request.js +2 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +73 -7
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +58 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +25 -0
- package/dist/member/types.js.map +1 -0
- package/dist/member/util.js +132 -25
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +10 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +102 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +106 -38
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js +15 -0
- package/dist/members/types.js.map +1 -0
- package/dist/members/util.js +326 -232
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +18 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +1 -446
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +223 -32
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +10 -0
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +39 -36
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +3 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +76 -5
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +366 -104
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +255 -0
- package/dist/multistream/sendSlotManager.js.map +1 -0
- package/dist/reachability/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +263 -390
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +6 -4
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- package/dist/reconnection-manager/index.js +266 -202
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/index.js +21 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +9 -8
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +51 -28
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +48 -64
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +220 -70
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +12 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +179 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/index.js +357 -295
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +296 -156
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +42 -0
- package/dist/types/annotation/constants.d.ts +31 -0
- package/dist/types/annotation/index.d.ts +117 -0
- package/dist/types/breakouts/events.d.ts +8 -0
- package/dist/types/breakouts/utils.d.ts +14 -0
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/types/common/errors/webex-errors.d.ts +25 -1
- package/dist/types/common/logs/request.d.ts +2 -0
- package/dist/types/common/queue.d.ts +9 -7
- package/dist/types/config.d.ts +2 -7
- package/dist/types/constants.d.ts +203 -31
- package/dist/types/controls-options-manager/enums.d.ts +11 -1
- package/dist/types/controls-options-manager/index.d.ts +17 -1
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -7
- package/dist/types/index.d.ts +6 -5
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -0
- package/dist/types/interpretation/collection.d.ts +5 -0
- package/dist/types/interpretation/index.d.ts +5 -0
- package/dist/types/interpretation/siLanguage.d.ts +5 -0
- package/dist/types/locus-info/index.d.ts +57 -4
- package/dist/types/locus-info/parser.d.ts +66 -6
- package/dist/types/media/index.d.ts +2 -0
- package/dist/types/media/properties.d.ts +34 -49
- package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
- package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
- package/dist/types/meeting/index.d.ts +567 -496
- package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/types/meeting/muteState.d.ts +93 -25
- package/dist/types/meeting/request.d.ts +64 -43
- package/dist/types/meeting/util.d.ts +117 -1
- package/dist/types/meeting-info/index.d.ts +13 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
- package/dist/types/meetings/collection.d.ts +17 -0
- package/dist/types/meetings/index.d.ts +113 -21
- package/dist/types/meetings/meetings.types.d.ts +4 -0
- package/dist/types/member/index.d.ts +14 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/members/collection.d.ts +5 -0
- package/dist/types/members/index.d.ts +35 -2
- package/dist/types/members/request.d.ts +73 -9
- package/dist/types/members/types.d.ts +25 -0
- package/dist/types/members/util.d.ts +214 -1
- package/dist/types/metrics/constants.d.ts +17 -0
- package/dist/types/metrics/index.d.ts +4 -111
- package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
- package/dist/types/multistream/receiveSlot.d.ts +7 -3
- package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
- package/dist/types/multistream/remoteMedia.d.ts +3 -31
- package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
- package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
- package/dist/types/multistream/sendSlotManager.d.ts +70 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +60 -95
- package/dist/types/reachability/request.d.ts +3 -1
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reconnection-manager/index.d.ts +19 -0
- package/dist/types/recording-controller/index.d.ts +15 -1
- package/dist/types/recording-controller/util.d.ts +5 -4
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/request.d.ts +9 -8
- package/dist/types/roap/turnDiscovery.d.ts +39 -5
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +61 -0
- package/dist/types/statsAnalyzer/index.d.ts +34 -12
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
- package/dist/types/webinar/collection.d.ts +16 -0
- package/dist/types/webinar/index.d.ts +5 -0
- package/dist/webinar/collection.js +44 -0
- package/dist/webinar/collection.js.map +1 -0
- package/dist/webinar/index.js +69 -0
- package/dist/webinar/index.js.map +1 -0
- package/package.json +22 -19
- package/src/annotation/annotation.types.ts +50 -0
- package/src/annotation/constants.ts +36 -0
- package/src/annotation/index.ts +328 -0
- package/src/breakouts/README.md +35 -11
- package/src/breakouts/breakout.ts +67 -9
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +558 -59
- package/src/breakouts/utils.ts +42 -0
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/common/errors/reclaim-host-role-errors.ts +134 -0
- package/src/common/errors/webex-errors.ts +44 -2
- package/src/common/logs/logger-proxy.ts +1 -1
- package/src/common/logs/request.ts +5 -1
- package/src/common/queue.ts +22 -8
- package/src/config.ts +4 -9
- package/src/constants.ts +229 -21
- package/src/controls-options-manager/enums.ts +12 -0
- package/src/controls-options-manager/index.ts +116 -21
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +294 -14
- package/src/index.ts +44 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +349 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +108 -0
- package/src/locus-info/index.ts +417 -59
- package/src/locus-info/infoUtils.ts +10 -2
- package/src/locus-info/mediaSharesUtils.ts +80 -0
- package/src/locus-info/parser.ts +258 -47
- package/src/locus-info/selfUtils.ts +81 -5
- package/src/media/index.ts +100 -108
- package/src/media/properties.ts +88 -117
- package/src/mediaQualityMetrics/config.ts +103 -238
- package/src/meeting/in-meeting-actions.ts +171 -3
- package/src/meeting/index.ts +3411 -2435
- package/src/meeting/locusMediaRequest.ts +313 -0
- package/src/meeting/muteState.ts +223 -136
- package/src/meeting/request.ts +155 -120
- package/src/meeting/util.ts +685 -395
- package/src/meeting-info/index.ts +81 -8
- package/src/meeting-info/meeting-info-v2.ts +170 -14
- package/src/meeting-info/util.ts +1 -1
- package/src/meeting-info/utilv2.ts +23 -23
- package/src/meetings/collection.ts +33 -0
- package/src/meetings/index.ts +507 -127
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/request.ts +2 -0
- package/src/meetings/util.ts +81 -12
- package/src/member/index.ts +58 -0
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +141 -25
- package/src/members/collection.ts +8 -0
- package/src/members/index.ts +134 -8
- package/src/members/request.ts +97 -17
- package/src/members/types.ts +29 -0
- package/src/members/util.ts +333 -240
- package/src/metrics/constants.ts +17 -0
- package/src/metrics/index.ts +1 -469
- package/src/multistream/mediaRequestManager.ts +271 -56
- package/src/multistream/receiveSlot.ts +11 -4
- package/src/multistream/receiveSlotManager.ts +34 -24
- package/src/multistream/remoteMedia.ts +5 -3
- package/src/multistream/remoteMediaGroup.ts +78 -0
- package/src/multistream/remoteMediaManager.ts +248 -44
- package/src/multistream/sendSlotManager.ts +199 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +229 -346
- package/src/reachability/request.ts +8 -4
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +128 -97
- package/src/recording-controller/index.ts +20 -3
- package/src/recording-controller/util.ts +26 -9
- package/src/roap/index.ts +52 -23
- package/src/roap/request.ts +48 -67
- package/src/roap/turnDiscovery.ts +147 -49
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +166 -0
- package/src/statsAnalyzer/index.ts +457 -416
- package/src/statsAnalyzer/mqaUtil.ts +317 -170
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +60 -3
- package/test/integration/spec/journey.js +320 -261
- package/test/integration/spec/space-meeting.js +76 -3
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +118 -28
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1349 -114
- package/test/unit/spec/breakouts/utils.js +52 -1
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +163 -0
- package/test/unit/spec/controls-options-manager/util.js +576 -60
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +625 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +316 -43
- package/test/unit/spec/locus-info/index.js +1363 -37
- package/test/unit/spec/locus-info/infoUtils.js +37 -15
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
- package/test/unit/spec/locus-info/parser.js +116 -35
- package/test/unit/spec/locus-info/selfConstant.js +27 -4
- package/test/unit/spec/locus-info/selfUtils.js +208 -17
- package/test/unit/spec/media/index.ts +173 -81
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
- package/test/unit/spec/meeting/index.js +6821 -2172
- package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
- package/test/unit/spec/meeting/muteState.js +402 -212
- package/test/unit/spec/meeting/request.js +473 -54
- package/test/unit/spec/meeting/utils.js +773 -67
- package/test/unit/spec/meeting-info/index.js +300 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
- package/test/unit/spec/meeting-info/utilv2.js +21 -0
- package/test/unit/spec/meetings/collection.js +26 -0
- package/test/unit/spec/meetings/index.js +1415 -213
- package/test/unit/spec/meetings/utils.js +229 -2
- package/test/unit/spec/member/index.js +61 -6
- package/test/unit/spec/member/util.js +510 -34
- package/test/unit/spec/members/index.js +432 -1
- package/test/unit/spec/members/request.js +206 -27
- package/test/unit/spec/members/utils.js +210 -0
- package/test/unit/spec/metrics/index.js +1 -50
- package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
- package/test/unit/spec/multistream/receiveSlot.ts +9 -1
- package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
- package/test/unit/spec/multistream/remoteMedia.ts +2 -0
- package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
- package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +551 -14
- package/test/unit/spec/reachability/request.js +3 -1
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +171 -11
- package/test/unit/spec/recording-controller/index.js +294 -218
- package/test/unit/spec/recording-controller/util.js +223 -96
- package/test/unit/spec/roap/index.ts +180 -83
- package/test/unit/spec/roap/request.ts +100 -62
- package/test/unit/spec/roap/turnDiscovery.ts +388 -96
- package/test/unit/spec/rtcMetrics/index.ts +122 -0
- package/test/unit/spec/stats-analyzer/index.js +1252 -12
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +0 -57
- package/test/utils/webex-test-users.js +12 -4
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/types/metrics/config.d.ts +0 -169
- package/src/index.js +0 -18
- package/src/metrics/config.ts +0 -485
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import SendSlotManager from '@webex/plugin-meetings/src/multistream/sendSlotManager';
|
|
2
|
+
import { LocalStream, MediaType, MultistreamRoapMediaConnection } from "@webex/internal-media-core";
|
|
3
|
+
import {expect} from '@webex/test-helper-chai';
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
|
|
6
|
+
describe('SendSlotsManager', () => {
|
|
7
|
+
let sendSlotsManager: SendSlotManager;
|
|
8
|
+
const LoggerProxy = {
|
|
9
|
+
logger: {
|
|
10
|
+
info: sinon.stub(),
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
sendSlotsManager = new SendSlotManager(LoggerProxy);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('createSlot', () => {
|
|
19
|
+
let mediaConnection;
|
|
20
|
+
const mediaType = MediaType.AudioMain;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
mediaConnection = {
|
|
24
|
+
createSendSlot: sinon.stub(),
|
|
25
|
+
} as MultistreamRoapMediaConnection;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should create a slot for the given mediaType', () => {
|
|
29
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
30
|
+
|
|
31
|
+
expect(mediaConnection.createSendSlot.calledWith(mediaType, true));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should create a slot for the given mediaType & active state', () => {
|
|
35
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType, false);
|
|
36
|
+
|
|
37
|
+
expect(mediaConnection.createSendSlot.calledWith(mediaType, false));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should throw an error if a slot for the given mediaType already exists', () => {
|
|
41
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
42
|
+
|
|
43
|
+
expect(() => sendSlotsManager.createSlot(mediaConnection, mediaType)).to.throw(`Slot for ${mediaType} already exists`);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('getSlot', () => {
|
|
48
|
+
const mediaType = MediaType.AudioMain;
|
|
49
|
+
let mediaConnection;
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
mediaConnection = {
|
|
53
|
+
createSendSlot: sinon.stub().returns({}),
|
|
54
|
+
} as MultistreamRoapMediaConnection;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should return the slot for the given mediaType', () => {
|
|
58
|
+
const slot = sendSlotsManager.createSlot(mediaConnection,mediaType);
|
|
59
|
+
|
|
60
|
+
expect(sendSlotsManager.getSlot(mediaType)).to.equal(slot);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should throw an error if a slot for the given mediaType does not exist', () => {
|
|
64
|
+
expect(() => sendSlotsManager.getSlot(mediaType)).to.throw(`Slot for ${mediaType} does not exist`);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('publishStream', () => {
|
|
69
|
+
let mediaConnection;
|
|
70
|
+
const mediaType = MediaType.AudioMain;
|
|
71
|
+
const stream = {} as LocalStream;
|
|
72
|
+
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
mediaConnection = {
|
|
75
|
+
createSendSlot: sinon.stub(),
|
|
76
|
+
} as MultistreamRoapMediaConnection;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should publish the given stream to the sendSlot for the given mediaType', async () => {
|
|
80
|
+
const slot = {
|
|
81
|
+
publishStream: sinon.stub().resolves(),
|
|
82
|
+
};
|
|
83
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
84
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
85
|
+
|
|
86
|
+
await sendSlotsManager.publishStream(mediaType, stream);
|
|
87
|
+
|
|
88
|
+
expect(slot.publishStream.calledWith(stream));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should throw an error if a slot for the given mediaType does not exist', (done) => {
|
|
92
|
+
sendSlotsManager.publishStream(mediaType, stream).catch((error) => {
|
|
93
|
+
expect(error.message).to.equal(`Slot for ${mediaType} does not exist`);
|
|
94
|
+
done();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('unpublishStream', () => {
|
|
100
|
+
let mediaConnection;
|
|
101
|
+
const mediaType = MediaType.AudioMain;
|
|
102
|
+
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
mediaConnection = {
|
|
105
|
+
createSendSlot: sinon.stub(),
|
|
106
|
+
} as MultistreamRoapMediaConnection;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should unpublish the stream from the sendSlot of the given mediaType', async () => {
|
|
110
|
+
const slot = {
|
|
111
|
+
unpublishStream: sinon.stub().resolves(),
|
|
112
|
+
};
|
|
113
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
114
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
115
|
+
|
|
116
|
+
await sendSlotsManager.unpublishStream(mediaType);
|
|
117
|
+
|
|
118
|
+
expect(slot.unpublishStream.called);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should throw an error if a slot for the given mediaType does not exist',(done) => {
|
|
122
|
+
sendSlotsManager.unpublishStream(mediaType).catch((error) => {
|
|
123
|
+
expect(error.message).to.equal(`Slot for ${mediaType} does not exist`);
|
|
124
|
+
done();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('setNamedMediaGroups', () => {
|
|
130
|
+
let mediaConnection;
|
|
131
|
+
const mediaType = MediaType.AudioMain;
|
|
132
|
+
const groups = [{type: 1, value: 20}];
|
|
133
|
+
|
|
134
|
+
beforeEach(() => {
|
|
135
|
+
mediaConnection = {
|
|
136
|
+
createSendSlot: sinon.stub(),
|
|
137
|
+
} as MultistreamRoapMediaConnection;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should publish the given stream to the sendSlot for the given mediaType', async () => {
|
|
141
|
+
const slot = {
|
|
142
|
+
setNamedMediaGroups: sinon.stub().resolves(),
|
|
143
|
+
};
|
|
144
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
145
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
146
|
+
|
|
147
|
+
await sendSlotsManager.setNamedMediaGroups(mediaType, groups);
|
|
148
|
+
|
|
149
|
+
expect(slot.setNamedMediaGroups.calledWith(groups));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should throw an error if the given mediaType is not audio', () => {
|
|
153
|
+
expect(() => sendSlotsManager.setNamedMediaGroups(MediaType.VideoMain, groups)).to.throw(`sendSlotManager cannot set named media group which media type is ${MediaType.VideoMain}`)
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should throw an error if a slot for the given mediaType does not exist', () => {
|
|
157
|
+
expect(() => sendSlotsManager.setNamedMediaGroups(mediaType, groups)).to.throw(`Slot for ${mediaType} does not exist`)
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('setActive', () => {
|
|
162
|
+
let mediaConnection;
|
|
163
|
+
const mediaType = MediaType.AudioMain;
|
|
164
|
+
|
|
165
|
+
beforeEach(() => {
|
|
166
|
+
mediaConnection = {
|
|
167
|
+
createSendSlot: sinon.stub(),
|
|
168
|
+
} as MultistreamRoapMediaConnection;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should set the active state of the sendSlot for the given mediaType', async () => {
|
|
172
|
+
const slot = {
|
|
173
|
+
setActive: sinon.stub().resolves(),
|
|
174
|
+
};
|
|
175
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
176
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
177
|
+
|
|
178
|
+
await sendSlotsManager.setActive(mediaType,true);
|
|
179
|
+
|
|
180
|
+
expect(slot.setActive.called);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('should throw an error if a slot for the given mediaType does not exist', () => {
|
|
184
|
+
expect(() => sendSlotsManager.setActive(mediaType)).to.throw(`Slot for ${mediaType} does not exist`)
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('setCodecParameters', () => {
|
|
189
|
+
let mediaConnection;
|
|
190
|
+
const mediaType = MediaType.AudioMain;
|
|
191
|
+
const codecParameters = {};
|
|
192
|
+
|
|
193
|
+
beforeEach(() => {
|
|
194
|
+
mediaConnection = {
|
|
195
|
+
createSendSlot: sinon.stub(),
|
|
196
|
+
} as MultistreamRoapMediaConnection;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should set the codec parameters of the sendSlot for the given mediaType', async () => {
|
|
200
|
+
const slot = {
|
|
201
|
+
setCodecParameters: sinon.stub().resolves(),
|
|
202
|
+
};
|
|
203
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
204
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
205
|
+
|
|
206
|
+
await sendSlotsManager.setCodecParameters(mediaType, codecParameters);
|
|
207
|
+
|
|
208
|
+
expect(slot.setCodecParameters.calledWith(codecParameters));
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should throw an error if a slot for the given mediaType does not exist', (done) => {
|
|
212
|
+
sendSlotsManager.setCodecParameters(mediaType, codecParameters).catch((error) => {
|
|
213
|
+
expect(error.message).to.equal(`Slot for ${mediaType} does not exist`);
|
|
214
|
+
done();
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('deleteCodecParameters', () => {
|
|
220
|
+
let mediaConnection;
|
|
221
|
+
const mediaType = MediaType.AudioMain;
|
|
222
|
+
|
|
223
|
+
beforeEach(() => {
|
|
224
|
+
mediaConnection = {
|
|
225
|
+
createSendSlot: sinon.stub(),
|
|
226
|
+
} as MultistreamRoapMediaConnection;
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should delete the codec parameters of the sendSlot for the given mediaType', async () => {
|
|
230
|
+
const slot = {
|
|
231
|
+
deleteCodecParameters: sinon.stub().resolves(),
|
|
232
|
+
};
|
|
233
|
+
mediaConnection.createSendSlot.returns(slot);
|
|
234
|
+
sendSlotsManager.createSlot(mediaConnection, mediaType);
|
|
235
|
+
|
|
236
|
+
await sendSlotsManager.deleteCodecParameters(mediaType,[]);
|
|
237
|
+
|
|
238
|
+
expect(slot.deleteCodecParameters.called);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should throw an error if a slot for the given mediaType does not exist', (done) => {
|
|
242
|
+
sendSlotsManager.deleteCodecParameters(mediaType,[]).catch((error) => {
|
|
243
|
+
expect(error.message).to.equal(`Slot for ${mediaType} does not exist`);
|
|
244
|
+
done();
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('reset', () => {
|
|
250
|
+
let mediaConnection;
|
|
251
|
+
|
|
252
|
+
beforeEach(() => {
|
|
253
|
+
mediaConnection = {
|
|
254
|
+
createSendSlot: sinon.stub().returns({}),
|
|
255
|
+
} as MultistreamRoapMediaConnection;
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should reset the send slot manager', () => {
|
|
259
|
+
const AudioSlot = sendSlotsManager.createSlot(mediaConnection, MediaType.AudioMain);
|
|
260
|
+
const VideoSlot = sendSlotsManager.createSlot(mediaConnection, MediaType.VideoMain);
|
|
261
|
+
const AudioSlidesSlot = sendSlotsManager.createSlot(mediaConnection, MediaType.AudioSlides);
|
|
262
|
+
const VideoSlidesSlot = sendSlotsManager.createSlot(mediaConnection, MediaType.VideoSlides);
|
|
263
|
+
expect(sendSlotsManager.getSlot(MediaType.AudioMain)).to.equal(AudioSlot);
|
|
264
|
+
expect(sendSlotsManager.getSlot(MediaType.VideoMain)).to.equal(VideoSlot);
|
|
265
|
+
expect(sendSlotsManager.getSlot(MediaType.AudioSlides)).to.equal(AudioSlidesSlot);
|
|
266
|
+
expect(sendSlotsManager.getSlot(MediaType.VideoSlides)).to.equal(VideoSlidesSlot);
|
|
267
|
+
sendSlotsManager.reset();
|
|
268
|
+
expect(() => sendSlotsManager.getSlot(MediaType.AudioMain)).to.throw();
|
|
269
|
+
expect(() => sendSlotsManager.getSlot(MediaType.VideoMain)).to.throw();
|
|
270
|
+
expect(() => sendSlotsManager.getSlot(MediaType.AudioSlides)).to.throw();
|
|
271
|
+
expect(() => sendSlotsManager.getSlot(MediaType.VideoSlides)).to.throw();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
});
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
3
|
+
import sinon from 'sinon';
|
|
4
|
+
import testUtils from '../../../utils/testUtils';
|
|
5
|
+
|
|
6
|
+
// packages/@webex/plugin-meetings/test/unit/spec/reachability/clusterReachability.ts
|
|
7
|
+
import { ClusterReachability } from '@webex/plugin-meetings/src/reachability/clusterReachability'; // replace with actual path
|
|
8
|
+
|
|
9
|
+
describe('ClusterReachability', () => {
|
|
10
|
+
let previousRTCPeerConnection;
|
|
11
|
+
let clusterReachability;
|
|
12
|
+
let fakePeerConnection;
|
|
13
|
+
|
|
14
|
+
const FAKE_OFFER = {type: 'offer', sdp: 'fake sdp'};
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
fakePeerConnection = {
|
|
18
|
+
createOffer: sinon.stub().resolves(FAKE_OFFER),
|
|
19
|
+
setLocalDescription: sinon.stub().resolves(),
|
|
20
|
+
close: sinon.stub(),
|
|
21
|
+
iceGatheringState: 'new',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
previousRTCPeerConnection = global.RTCPeerConnection;
|
|
25
|
+
global.RTCPeerConnection = sinon.stub().returns(fakePeerConnection);
|
|
26
|
+
|
|
27
|
+
clusterReachability = new ClusterReachability('testName', {
|
|
28
|
+
isVideoMesh: false,
|
|
29
|
+
udp: ['stun:udp1', 'stun:udp2'],
|
|
30
|
+
tcp: ['stun:tcp1.webex.com', 'stun:tcp2.webex.com:5004'],
|
|
31
|
+
xtls: ['xtls1', 'xtls2'],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
global.RTCPeerConnection = previousRTCPeerConnection;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should create an instance correctly', () => {
|
|
41
|
+
assert.instanceOf(clusterReachability, ClusterReachability);
|
|
42
|
+
assert.equal(clusterReachability.name, 'testName');
|
|
43
|
+
assert.equal(clusterReachability.isVideoMesh, false);
|
|
44
|
+
assert.equal(clusterReachability.numUdpUrls, 2);
|
|
45
|
+
assert.equal(clusterReachability.numTcpUrls, 2);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should create a peer connection with the right config', () => {
|
|
49
|
+
assert.calledOnceWithExactly(global.RTCPeerConnection, {
|
|
50
|
+
iceServers: [
|
|
51
|
+
{username: '', credential: '', urls: ['stun:udp1']},
|
|
52
|
+
{username: '', credential: '', urls: ['stun:udp2']},
|
|
53
|
+
{username: 'webexturnreachuser', credential: 'webexturnreachpwd', urls: ['turn:tcp1.webex.com?transport=tcp']},
|
|
54
|
+
{username: 'webexturnreachuser', credential: 'webexturnreachpwd', urls: ['turn:tcp2.webex.com:5004?transport=tcp']}
|
|
55
|
+
],
|
|
56
|
+
iceCandidatePoolSize: 0,
|
|
57
|
+
iceTransportPolicy: 'all',
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should create a peer connection with the right config even if lists of urls are empty', () => {
|
|
62
|
+
(global.RTCPeerConnection as any).resetHistory();
|
|
63
|
+
|
|
64
|
+
clusterReachability = new ClusterReachability('testName', {
|
|
65
|
+
isVideoMesh: false,
|
|
66
|
+
udp: [],
|
|
67
|
+
tcp: [],
|
|
68
|
+
xtls: [],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
assert.calledOnceWithExactly(global.RTCPeerConnection, {
|
|
72
|
+
iceServers: [],
|
|
73
|
+
iceCandidatePoolSize: 0,
|
|
74
|
+
iceTransportPolicy: 'all',
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('returns correct results before start() is called', () => {
|
|
79
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
80
|
+
udp: {result: 'untested'},
|
|
81
|
+
tcp: {result: 'untested'},
|
|
82
|
+
xtls: {result: 'untested'}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('#start', () => {
|
|
87
|
+
let clock;
|
|
88
|
+
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
clock = sinon.useFakeTimers();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
clock.restore();
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should initiate the ICE gathering process', async () => {
|
|
98
|
+
const promise = clusterReachability.start();
|
|
99
|
+
|
|
100
|
+
await testUtils.flushPromises();
|
|
101
|
+
|
|
102
|
+
// check that the right listeners are setup
|
|
103
|
+
assert.isFunction(fakePeerConnection.onicecandidate);
|
|
104
|
+
assert.isFunction(fakePeerConnection.onicegatheringstatechange);
|
|
105
|
+
|
|
106
|
+
// check that the right webrtc APIs are called
|
|
107
|
+
assert.calledOnceWithExactly(fakePeerConnection.createOffer, {offerToReceiveAudio: true});
|
|
108
|
+
assert.calledOnce(fakePeerConnection.setLocalDescription);
|
|
109
|
+
|
|
110
|
+
await clock.tickAsync(3000);// move the clock so that reachability times out
|
|
111
|
+
await promise;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('resolves and has correct result as soon as it finds that both udp and tcp is reachable', async () => {
|
|
115
|
+
const promise = clusterReachability.start();
|
|
116
|
+
|
|
117
|
+
await clock.tickAsync(100);
|
|
118
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp'}});
|
|
119
|
+
|
|
120
|
+
await clock.tickAsync(100);
|
|
121
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp'}});
|
|
122
|
+
|
|
123
|
+
await promise;
|
|
124
|
+
|
|
125
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
126
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['somePublicIp']},
|
|
127
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 200},
|
|
128
|
+
xtls: {result: 'untested'}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('times out correctly', async () => {
|
|
133
|
+
const promise = clusterReachability.start();
|
|
134
|
+
|
|
135
|
+
// progress time without any candidates
|
|
136
|
+
await clock.tickAsync(3000);
|
|
137
|
+
await promise;
|
|
138
|
+
|
|
139
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
140
|
+
udp: {result: 'unreachable'},
|
|
141
|
+
tcp: {result: 'unreachable'},
|
|
142
|
+
xtls: {result: 'untested'}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('times out correctly for video mesh nodes', async () => {
|
|
147
|
+
clusterReachability = new ClusterReachability('testName', {
|
|
148
|
+
isVideoMesh: true,
|
|
149
|
+
udp: ['stun:udp1', 'stun:udp2'],
|
|
150
|
+
tcp: ['stun:tcp1.webex.com', 'stun:tcp2.webex.com:5004'],
|
|
151
|
+
xtls: ['xtls1', 'xtls2'],
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const promise = clusterReachability.start();
|
|
155
|
+
|
|
156
|
+
// video mesh nodes have shorter timeout of just 1s
|
|
157
|
+
await clock.tickAsync(1000);
|
|
158
|
+
await promise;
|
|
159
|
+
|
|
160
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
161
|
+
udp: {result: 'unreachable'},
|
|
162
|
+
tcp: {result: 'unreachable'},
|
|
163
|
+
xtls: {result: 'untested'}
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('resolves when ICE gathering is completed', async () => {
|
|
168
|
+
const promise = clusterReachability.start();
|
|
169
|
+
|
|
170
|
+
await testUtils.flushPromises();
|
|
171
|
+
|
|
172
|
+
fakePeerConnection.iceConnectionState = 'complete';
|
|
173
|
+
fakePeerConnection.onicegatheringstatechange();
|
|
174
|
+
await promise;
|
|
175
|
+
|
|
176
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
177
|
+
udp: {result: 'unreachable'},
|
|
178
|
+
tcp: {result: 'unreachable'},
|
|
179
|
+
xtls: {result: 'untested'}
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('resolves with the right result when ICE gathering is completed', async () => {
|
|
184
|
+
const promise = clusterReachability.start();
|
|
185
|
+
|
|
186
|
+
// send 1 candidate
|
|
187
|
+
await clock.tickAsync(30);
|
|
188
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp1'}});
|
|
189
|
+
|
|
190
|
+
fakePeerConnection.iceConnectionState = 'complete';
|
|
191
|
+
fakePeerConnection.onicegatheringstatechange();
|
|
192
|
+
await promise;
|
|
193
|
+
|
|
194
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
195
|
+
udp: {result: 'reachable', latencyInMilliseconds: 30, clientMediaIPs: ['somePublicIp1']},
|
|
196
|
+
tcp: {result: 'unreachable'},
|
|
197
|
+
xtls: {result: 'untested'}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should store latency only for the first srflx candidate, but IPs from all of them', async () => {
|
|
202
|
+
const promise = clusterReachability.start();
|
|
203
|
+
|
|
204
|
+
await clock.tickAsync(10);
|
|
205
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp1'}});
|
|
206
|
+
|
|
207
|
+
// generate more candidates
|
|
208
|
+
await clock.tickAsync(10);
|
|
209
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp2'}});
|
|
210
|
+
|
|
211
|
+
await clock.tickAsync(10);
|
|
212
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp3'}});
|
|
213
|
+
|
|
214
|
+
await clock.tickAsync(3000);// move the clock so that reachability times out
|
|
215
|
+
|
|
216
|
+
await promise;
|
|
217
|
+
|
|
218
|
+
// latency should be from only the first candidates, but the clientMediaIps should be from all UDP candidates (not TCP)
|
|
219
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
220
|
+
udp: {result: 'reachable', latencyInMilliseconds: 10, clientMediaIPs: ['somePublicIp1', 'somePublicIp2', 'somePublicIp3']},
|
|
221
|
+
tcp: {result: 'unreachable'},
|
|
222
|
+
xtls: {result: 'untested'}
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should store latency only for the first relay candidate', async () => {
|
|
227
|
+
const promise = clusterReachability.start();
|
|
228
|
+
|
|
229
|
+
await clock.tickAsync(10);
|
|
230
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp1'}});
|
|
231
|
+
|
|
232
|
+
// generate more candidates
|
|
233
|
+
await clock.tickAsync(10);
|
|
234
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp2'}});
|
|
235
|
+
|
|
236
|
+
await clock.tickAsync(10);
|
|
237
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp3'}});
|
|
238
|
+
|
|
239
|
+
await clock.tickAsync(3000);// move the clock so that reachability times out
|
|
240
|
+
|
|
241
|
+
await promise;
|
|
242
|
+
|
|
243
|
+
// latency should be from only the first candidates, but the clientMediaIps should be from only from UDP candidates
|
|
244
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
245
|
+
udp: {result: 'unreachable'},
|
|
246
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 10},
|
|
247
|
+
xtls: {result: 'untested'}
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('ignores duplicate clientMediaIps', async () => {
|
|
252
|
+
const promise = clusterReachability.start();
|
|
253
|
+
|
|
254
|
+
// generate candidates with duplicate addresses
|
|
255
|
+
await clock.tickAsync(10);
|
|
256
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp1'}});
|
|
257
|
+
|
|
258
|
+
await clock.tickAsync(10);
|
|
259
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp1'}});
|
|
260
|
+
|
|
261
|
+
await clock.tickAsync(10);
|
|
262
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp2'}});
|
|
263
|
+
|
|
264
|
+
await clock.tickAsync(10);
|
|
265
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp2'}});
|
|
266
|
+
|
|
267
|
+
// send also a relay candidate so that the reachability check finishes
|
|
268
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp'}});
|
|
269
|
+
|
|
270
|
+
await promise;
|
|
271
|
+
|
|
272
|
+
assert.deepEqual(clusterReachability.getResult(), {
|
|
273
|
+
udp: {result: 'reachable', latencyInMilliseconds: 10, clientMediaIPs: ['somePublicIp1', 'somePublicIp2']},
|
|
274
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 40},
|
|
275
|
+
xtls: {result: 'untested'}
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|