@webex/plugin-meetings 3.0.0-stream-classes.4 → 3.0.0-test.1
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/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 +23 -3
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/logs/request.js +5 -1
- package/dist/common/logs/request.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +69 -9
- package/dist/constants.js.map +1 -1
- package/dist/index.js +11 -1
- 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/index.js +16 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +40 -11
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +15 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +42 -21
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/index.js +10 -6
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +13 -3
- 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 +4 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +2187 -1074
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +37 -25
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +34 -19
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +71 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +48 -23
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +25 -4
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +1 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +17 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +142 -57
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +2 -6
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +11 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +17 -1
- package/dist/members/index.js.map +1 -1
- package/dist/members/types.js.map +1 -1
- package/dist/members/util.js +15 -4
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +15 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +16 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +222 -73
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +22 -0
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +262 -432
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +1 -1
- 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 +113 -96
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +57 -25
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +5 -13
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +173 -81
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/index.js +68 -6
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +338 -289
- 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/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 +13 -1
- package/dist/types/common/logs/request.d.ts +2 -0
- package/dist/types/config.d.ts +1 -1
- package/dist/types/constants.d.ts +66 -13
- package/dist/types/index.d.ts +1 -1
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -0
- package/dist/types/locus-info/index.d.ts +1 -1
- package/dist/types/locus-info/parser.d.ts +3 -2
- package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
- package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
- package/dist/types/meeting/index.d.ts +285 -34
- package/dist/types/meeting/locusMediaRequest.d.ts +1 -2
- package/dist/types/meeting/muteState.d.ts +2 -8
- package/dist/types/meeting/request.d.ts +4 -1
- package/dist/types/meeting/util.d.ts +25 -1
- package/dist/types/meeting-info/index.d.ts +7 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +1 -0
- package/dist/types/meetings/collection.d.ts +9 -0
- package/dist/types/meetings/index.d.ts +42 -14
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/members/types.d.ts +1 -0
- package/dist/types/members/util.d.ts +5 -0
- package/dist/types/metrics/constants.d.ts +15 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +2 -0
- package/dist/types/multistream/remoteMediaGroup.d.ts +2 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +25 -1
- package/dist/types/multistream/sendSlotManager.d.ts +9 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +59 -112
- package/dist/types/reachability/request.d.ts +1 -1
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reconnection-manager/index.d.ts +10 -0
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/request.d.ts +2 -1
- package/dist/types/roap/turnDiscovery.d.ts +21 -4
- package/dist/types/rtcMetrics/index.d.ts +15 -1
- package/dist/types/statsAnalyzer/index.d.ts +28 -11
- 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 +3 -2
- 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 +19 -2
- package/src/common/logs/request.ts +5 -1
- package/src/config.ts +1 -1
- package/src/constants.ts +71 -6
- package/src/index.ts +5 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/interpretation/index.ts +18 -1
- package/src/locus-info/index.ts +52 -16
- package/src/locus-info/mediaSharesUtils.ts +16 -0
- package/src/locus-info/parser.ts +47 -21
- package/src/media/index.ts +8 -6
- package/src/media/properties.ts +17 -2
- package/src/mediaQualityMetrics/config.ts +103 -238
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +1510 -529
- package/src/meeting/muteState.ts +34 -20
- package/src/meeting/request.ts +19 -1
- package/src/meeting/util.ts +97 -0
- package/src/meeting-info/index.ts +47 -20
- package/src/meeting-info/meeting-info-v2.ts +27 -5
- package/src/meeting-info/utilv2.ts +1 -1
- package/src/meetings/collection.ts +13 -0
- package/src/meetings/index.ts +112 -31
- package/src/meetings/util.ts +2 -8
- package/src/member/index.ts +9 -0
- package/src/member/util.ts +14 -0
- package/src/members/index.ts +29 -2
- package/src/members/types.ts +1 -0
- package/src/members/util.ts +15 -1
- package/src/metrics/constants.ts +14 -0
- package/src/multistream/mediaRequestManager.ts +4 -1
- package/src/multistream/remoteMediaGroup.ts +19 -0
- package/src/multistream/remoteMediaManager.ts +141 -18
- package/src/multistream/sendSlotManager.ts +29 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +221 -382
- package/src/reachability/request.ts +1 -1
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +87 -83
- package/src/roap/index.ts +60 -24
- package/src/roap/request.ts +3 -16
- package/src/roap/turnDiscovery.ts +112 -39
- package/src/rtcMetrics/index.ts +71 -5
- package/src/statsAnalyzer/index.ts +430 -427
- package/src/statsAnalyzer/mqaUtil.ts +317 -168
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +7 -7
- package/test/integration/spec/journey.js +86 -104
- package/test/integration/spec/space-meeting.js +9 -9
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/interpretation/index.ts +36 -3
- package/test/unit/spec/locus-info/index.js +205 -12
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +10 -0
- package/test/unit/spec/locus-info/parser.js +54 -13
- package/test/unit/spec/media/index.ts +20 -4
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +4027 -1075
- package/test/unit/spec/meeting/muteState.js +219 -67
- package/test/unit/spec/meeting/request.js +63 -12
- package/test/unit/spec/meeting/utils.js +93 -0
- package/test/unit/spec/meeting-info/index.js +180 -61
- package/test/unit/spec/meeting-info/meetinginfov2.js +196 -53
- package/test/unit/spec/meetings/collection.js +12 -0
- package/test/unit/spec/meetings/index.js +619 -206
- package/test/unit/spec/meetings/utils.js +35 -12
- package/test/unit/spec/member/index.js +8 -7
- package/test/unit/spec/member/util.js +32 -0
- package/test/unit/spec/members/index.js +130 -17
- package/test/unit/spec/members/utils.js +26 -0
- package/test/unit/spec/multistream/mediaRequestManager.ts +20 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +80 -1
- package/test/unit/spec/multistream/remoteMediaManager.ts +210 -3
- package/test/unit/spec/multistream/sendSlotManager.ts +50 -18
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +505 -135
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +74 -17
- package/test/unit/spec/roap/index.ts +181 -61
- package/test/unit/spec/roap/request.ts +27 -3
- package/test/unit/spec/roap/turnDiscovery.ts +362 -101
- package/test/unit/spec/rtcMetrics/index.ts +57 -3
- package/test/unit/spec/stats-analyzer/index.js +1225 -12
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/integrationTestUtils.js +4 -4
- package/test/utils/webex-test-users.js +12 -4
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
2
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
3
3
|
import sinon from 'sinon';
|
|
4
|
-
import Reachability, {
|
|
4
|
+
import Reachability, {ReachabilityResults, ReachabilityResultsForBackend} from '@webex/plugin-meetings/src/reachability/';
|
|
5
5
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
6
|
+
import * as ClusterReachabilityModule from '@webex/plugin-meetings/src/reachability/clusterReachability';
|
|
6
7
|
|
|
7
8
|
import { IP_VERSION } from '@webex/plugin-meetings/src/constants';
|
|
8
9
|
|
|
9
|
-
describe('
|
|
10
|
+
describe('isAnyPublicClusterReachable', () => {
|
|
10
11
|
let webex;
|
|
11
12
|
|
|
12
13
|
beforeEach(() => {
|
|
@@ -29,25 +30,25 @@ describe('isAnyClusterReachable', () => {
|
|
|
29
30
|
}
|
|
30
31
|
const reachability = new Reachability(webex);
|
|
31
32
|
|
|
32
|
-
const result = await reachability.
|
|
33
|
+
const result = await reachability.isAnyPublicClusterReachable();
|
|
33
34
|
|
|
34
35
|
assert.equal(result, expectedValue);
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
it('returns true when udp is reachable', async () => {
|
|
38
|
-
await checkIsClusterReachable({x: {udp: {
|
|
39
|
+
await checkIsClusterReachable({x: {udp: {result: 'reachable'}, tcp: {result: 'unreachable'}}}, true);
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it('returns true when tcp is reachable', async () => {
|
|
42
|
-
await checkIsClusterReachable({x: {udp: {
|
|
43
|
+
await checkIsClusterReachable({x: {udp: {result: 'unreachable'}, tcp: {result: 'reachable'}}}, true);
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
it('returns true when both tcp and udp are reachable', async () => {
|
|
46
|
-
await checkIsClusterReachable({x: {udp: {
|
|
47
|
+
await checkIsClusterReachable({x: {udp: {result: 'reachable'}, tcp: {result: 'reachable'}}}, true);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
it('returns false when both tcp and udp are unreachable', async () => {
|
|
50
|
-
await checkIsClusterReachable({x: {udp: {
|
|
51
|
+
await checkIsClusterReachable({x: {udp: {result: 'unreachable'}, tcp: {result: 'unreachable'}}}, false);
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
it('returns false when reachability result is empty', async () => {
|
|
@@ -57,6 +58,63 @@ describe('isAnyClusterReachable', () => {
|
|
|
57
58
|
it('returns false when reachability.result item is not there', async () => {
|
|
58
59
|
await checkIsClusterReachable(undefined, false);
|
|
59
60
|
});
|
|
61
|
+
|
|
62
|
+
describe('ignores video mesh reachability', () => {
|
|
63
|
+
it('returns false if there are no public cluster results, only video mesh', async () => {
|
|
64
|
+
await checkIsClusterReachable({
|
|
65
|
+
x: {
|
|
66
|
+
udp: {result: 'reachable'},
|
|
67
|
+
tcp: {result: 'reachable'},
|
|
68
|
+
isVideoMesh: true,
|
|
69
|
+
},
|
|
70
|
+
y: {
|
|
71
|
+
udp: {result: 'unreachable'},
|
|
72
|
+
tcp: {result: 'reachable'},
|
|
73
|
+
isVideoMesh: true,
|
|
74
|
+
}
|
|
75
|
+
}, false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('returns false if there public cluster reachability failed, only video mesh succeeded', async () => {
|
|
79
|
+
await checkIsClusterReachable({
|
|
80
|
+
x: {
|
|
81
|
+
udp: {result: 'unreachable'},
|
|
82
|
+
tcp: {result: 'reachable'},
|
|
83
|
+
isVideoMesh: true,
|
|
84
|
+
},
|
|
85
|
+
y: {
|
|
86
|
+
udp: {result: 'reachable'},
|
|
87
|
+
tcp: {result: 'unreachable'},
|
|
88
|
+
isVideoMesh: true,
|
|
89
|
+
},
|
|
90
|
+
publicOne: {
|
|
91
|
+
udp: {result: 'unreachable'},
|
|
92
|
+
tcp: {result: 'unreachable'},
|
|
93
|
+
isVideoMesh: false,
|
|
94
|
+
}
|
|
95
|
+
}, false);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('returns true if there is at least 1 public cluster result, while video mesh is not reachable', async () => {
|
|
99
|
+
await checkIsClusterReachable({
|
|
100
|
+
x: {
|
|
101
|
+
udp: {result: 'reachable'},
|
|
102
|
+
tcp: {result: 'reachable'},
|
|
103
|
+
isVideoMesh: true,
|
|
104
|
+
},
|
|
105
|
+
y: {
|
|
106
|
+
udp: {result: 'unreachable'},
|
|
107
|
+
tcp: {result: 'reachable'},
|
|
108
|
+
isVideoMesh: true,
|
|
109
|
+
},
|
|
110
|
+
publicOne: {
|
|
111
|
+
udp: {result: 'unreachable'},
|
|
112
|
+
tcp: {result: 'reachable'},
|
|
113
|
+
isVideoMesh: false,
|
|
114
|
+
}
|
|
115
|
+
}, true);
|
|
116
|
+
});
|
|
117
|
+
})
|
|
60
118
|
});
|
|
61
119
|
|
|
62
120
|
describe('gatherReachability', () => {
|
|
@@ -70,6 +128,15 @@ describe('gatherReachability', () => {
|
|
|
70
128
|
'reachability.result',
|
|
71
129
|
JSON.stringify({old: 'results'})
|
|
72
130
|
);
|
|
131
|
+
await webex.boundedStorage.put(
|
|
132
|
+
'Reachability',
|
|
133
|
+
'reachability.joinCookie',
|
|
134
|
+
JSON.stringify({old: 'joinCookie'})
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
afterEach(() => {
|
|
139
|
+
sinon.restore();
|
|
73
140
|
});
|
|
74
141
|
|
|
75
142
|
it('stores the reachability', async () => {
|
|
@@ -88,7 +155,7 @@ describe('gatherReachability', () => {
|
|
|
88
155
|
};
|
|
89
156
|
|
|
90
157
|
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
91
|
-
(reachability as any).
|
|
158
|
+
(reachability as any).performReachabilityChecks = sinon.stub().returns(reachabilityResults);
|
|
92
159
|
|
|
93
160
|
const result = await reachability.gatherReachability();
|
|
94
161
|
|
|
@@ -107,156 +174,459 @@ describe('gatherReachability', () => {
|
|
|
107
174
|
assert.equal(JSON.stringify(getClustersResult.joinCookie), storedResultForJoinCookie);
|
|
108
175
|
});
|
|
109
176
|
|
|
110
|
-
it('
|
|
177
|
+
it('keeps the stored reachability from previous call to gatherReachability if getClusters fails', async () => {
|
|
111
178
|
const reachability = new Reachability(webex);
|
|
112
179
|
|
|
180
|
+
const reachabilityResults = {
|
|
181
|
+
clusters: {
|
|
182
|
+
clusterId: {
|
|
183
|
+
udp: 'testUDP',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
};
|
|
113
187
|
const getClustersResult = {
|
|
114
|
-
clusters: {clusterId:
|
|
115
|
-
tcp: [
|
|
116
|
-
'stun:170.72.164.1:5004',
|
|
117
|
-
'stun:170.72.165.2:5004'
|
|
118
|
-
],
|
|
119
|
-
udp: [
|
|
120
|
-
'stun:170.72.164.3:5004',
|
|
121
|
-
'stun:170.72.164.3:9000',
|
|
122
|
-
],
|
|
123
|
-
xtls: [
|
|
124
|
-
'stun:external-media101.public.wjfkm-a-4.prod.infra.webex.com:443',
|
|
125
|
-
'stun:external-media94.public.wjfkm-a-8.prod.infra.webex.com:443'
|
|
126
|
-
]
|
|
127
|
-
}},
|
|
188
|
+
clusters: {clusterId: 'cluster'},
|
|
128
189
|
joinCookie: {id: 'id'},
|
|
129
190
|
};
|
|
130
191
|
|
|
131
|
-
sinon.stub(
|
|
192
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().throws();
|
|
132
193
|
|
|
133
|
-
const
|
|
194
|
+
const result = await reachability.gatherReachability();
|
|
134
195
|
|
|
135
|
-
|
|
196
|
+
assert.empty(result);
|
|
136
197
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
username: '',
|
|
149
|
-
credential: '',
|
|
150
|
-
urls: ['stun:170.72.164.3:9000'],
|
|
151
|
-
}
|
|
152
|
-
],
|
|
153
|
-
iceCandidatePoolSize: '0',
|
|
154
|
-
iceTransportPolicy: 'all'
|
|
155
|
-
}
|
|
156
|
-
})
|
|
198
|
+
const storedResultForReachabilityResult = await webex.boundedStorage.get(
|
|
199
|
+
'Reachability',
|
|
200
|
+
'reachability.result'
|
|
201
|
+
);
|
|
202
|
+
const storedResultForJoinCookie = await webex.boundedStorage.get(
|
|
203
|
+
'Reachability',
|
|
204
|
+
'reachability.joinCookie'
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
assert.equal(JSON.stringify({old: 'results'}), storedResultForReachabilityResult);
|
|
208
|
+
assert.equal(JSON.stringify({old: 'joinCookie'}), storedResultForJoinCookie);
|
|
157
209
|
});
|
|
158
210
|
|
|
159
|
-
|
|
160
|
-
|
|
211
|
+
it('keeps the stored reachability from previous call to gatherReachability if performReachabilityChecks fails', async () => {
|
|
212
|
+
const reachability = new Reachability(webex);
|
|
161
213
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
214
|
+
const reachabilityResults = {
|
|
215
|
+
clusters: {
|
|
216
|
+
clusterId: {
|
|
217
|
+
udp: 'testUDP',
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
const getClustersResult = {
|
|
222
|
+
clusters: {clusterId: 'cluster'},
|
|
223
|
+
joinCookie: {id: 'id'},
|
|
224
|
+
};
|
|
173
225
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
{
|
|
177
|
-
clusterId: 'id1',
|
|
178
|
-
elapsed: '12312',
|
|
179
|
-
publicIPs: ['1.1.1.1'],
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
clusterId: 'id2',
|
|
183
|
-
elapsed: null,
|
|
184
|
-
publicIPs: ['1.1.1.1'],
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
clusterId: 'id2',
|
|
188
|
-
elapsed: '14123',
|
|
189
|
-
publicIPs: undefined,
|
|
190
|
-
},
|
|
191
|
-
]);
|
|
192
|
-
|
|
193
|
-
assert.deepEqual(res, {
|
|
194
|
-
id1: {
|
|
195
|
-
tcp: {
|
|
196
|
-
untested: 'true',
|
|
197
|
-
},
|
|
198
|
-
xtls: {
|
|
199
|
-
untested: 'true',
|
|
200
|
-
},
|
|
201
|
-
udp: {
|
|
202
|
-
clientMediaIPs: ['1.1.1.1'],
|
|
203
|
-
latencyInMilliseconds: '12312',
|
|
204
|
-
reachable: 'true',
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
id2: {
|
|
208
|
-
xtls: {
|
|
209
|
-
untested: 'true',
|
|
210
|
-
},
|
|
211
|
-
tcp: {
|
|
212
|
-
untested: 'true',
|
|
213
|
-
},
|
|
214
|
-
udp: {
|
|
215
|
-
latencyInMilliseconds: '14123',
|
|
216
|
-
reachable: 'true',
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
});
|
|
226
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
227
|
+
(reachability as any).performReachabilityChecks = sinon.stub().throws();
|
|
221
228
|
|
|
222
|
-
|
|
223
|
-
const peerConnection = {
|
|
224
|
-
connectionState: 'not_closed',
|
|
225
|
-
};
|
|
229
|
+
const result = await reachability.gatherReachability();
|
|
226
230
|
|
|
227
|
-
|
|
231
|
+
assert.empty(result);
|
|
228
232
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
const storedResultForReachabilityResult = await webex.boundedStorage.get(
|
|
234
|
+
'Reachability',
|
|
235
|
+
'reachability.result'
|
|
236
|
+
);
|
|
237
|
+
const storedResultForJoinCookie = await webex.boundedStorage.get(
|
|
238
|
+
'Reachability',
|
|
239
|
+
'reachability.joinCookie'
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
assert.equal(JSON.stringify({old: 'results'}), storedResultForReachabilityResult);
|
|
243
|
+
assert.equal(JSON.stringify({old: 'joinCookie'}), storedResultForJoinCookie);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('starts ClusterReachability on each media cluster', async () => {
|
|
247
|
+
webex.config.meetings.experimental = {enableTcpReachability: true};
|
|
248
|
+
|
|
249
|
+
const getClustersResult = {
|
|
250
|
+
clusters: {
|
|
251
|
+
'cluster 1': {
|
|
252
|
+
udp: ['udp1.1', 'udp1.2'],
|
|
253
|
+
tcp: ['tcp1.1', 'tcp1.2'],
|
|
254
|
+
xtls: ['xtls1.1', 'xtls1.2'],
|
|
255
|
+
isVideoMesh: false,
|
|
256
|
+
},
|
|
257
|
+
'cluster 2': {
|
|
258
|
+
udp: ['udp2.1', 'udp2.2'],
|
|
259
|
+
tcp: ['tcp2.1', 'tcp2.2'],
|
|
260
|
+
xtls: ['xtls2.1', 'xtls2.2'],
|
|
261
|
+
isVideoMesh: true,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
joinCookie: {id: 'id'},
|
|
265
|
+
};
|
|
234
266
|
|
|
235
|
-
|
|
236
|
-
const peerConnection = {
|
|
237
|
-
connectionState: 'not_closed',
|
|
238
|
-
publicIPs: ['2.2.2.2'],
|
|
239
|
-
};
|
|
267
|
+
const reachability = new Reachability(webex);
|
|
240
268
|
|
|
241
|
-
|
|
269
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
270
|
+
|
|
271
|
+
const startStub = sinon.stub().resolves({});
|
|
272
|
+
const clusterReachabilityCtorStub = sinon
|
|
273
|
+
.stub(ClusterReachabilityModule, 'ClusterReachability')
|
|
274
|
+
.callsFake(() => ({
|
|
275
|
+
start: startStub,
|
|
276
|
+
}));
|
|
277
|
+
|
|
278
|
+
await reachability.gatherReachability();
|
|
242
279
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
280
|
+
assert.calledTwice(clusterReachabilityCtorStub);
|
|
281
|
+
assert.calledWith(clusterReachabilityCtorStub, 'cluster 1', {
|
|
282
|
+
udp: ['udp1.1', 'udp1.2'],
|
|
283
|
+
tcp: ['tcp1.1', 'tcp1.2'],
|
|
284
|
+
xtls: ['xtls1.1', 'xtls1.2'],
|
|
285
|
+
isVideoMesh: false,
|
|
286
|
+
});
|
|
287
|
+
// cluster 2 is video mesh, so we should not do TCP reachability on it
|
|
288
|
+
assert.calledWith(clusterReachabilityCtorStub, 'cluster 2', {
|
|
289
|
+
udp: ['udp2.1', 'udp2.2'],
|
|
290
|
+
tcp: [],
|
|
291
|
+
xtls: ['xtls2.1', 'xtls2.2'],
|
|
292
|
+
isVideoMesh: true,
|
|
247
293
|
});
|
|
248
294
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
connectionState: 'not_closed',
|
|
252
|
-
};
|
|
295
|
+
assert.calledTwice(startStub);
|
|
296
|
+
});
|
|
253
297
|
|
|
254
|
-
|
|
298
|
+
it('does not do TCP reachability if it is disabled in config', async () => {
|
|
299
|
+
webex.config.meetings.experimental = {enableTcpReachability: false};
|
|
255
300
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
301
|
+
const getClustersResult = {
|
|
302
|
+
clusters: {
|
|
303
|
+
'cluster name': {
|
|
304
|
+
udp: ['testUDP1', 'testUDP2'],
|
|
305
|
+
tcp: ['testTCP1', 'testTCP2'],
|
|
306
|
+
xtls: ['testXTLS1', 'testXTLS2'],
|
|
307
|
+
isVideoMesh: false,
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
joinCookie: {id: 'id'},
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const reachability = new Reachability(webex);
|
|
314
|
+
|
|
315
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
316
|
+
|
|
317
|
+
const clusterReachabilityCtorStub = sinon
|
|
318
|
+
.stub(ClusterReachabilityModule, 'ClusterReachability')
|
|
319
|
+
.callsFake(() => ({
|
|
320
|
+
start: sinon.stub().resolves({}),
|
|
321
|
+
}));
|
|
322
|
+
|
|
323
|
+
await reachability.gatherReachability();
|
|
324
|
+
|
|
325
|
+
assert.calledOnceWithExactly(clusterReachabilityCtorStub, 'cluster name', {
|
|
326
|
+
isVideoMesh: false,
|
|
327
|
+
udp: ['testUDP1', 'testUDP2'],
|
|
328
|
+
tcp: [], // empty list because TCP is disabled in config
|
|
329
|
+
xtls: ['testXTLS1', 'testXTLS2'],
|
|
260
330
|
});
|
|
261
331
|
});
|
|
262
332
|
});
|
|
333
|
+
|
|
334
|
+
describe('getReachabilityResults', () => {
|
|
335
|
+
let webex;
|
|
336
|
+
|
|
337
|
+
beforeEach(() => {
|
|
338
|
+
webex = new MockWebex();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
afterEach(() => {
|
|
342
|
+
sinon.restore();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const runCheck = async (mockStorage: any, expectedResult: ReachabilityResultsForBackend) => {
|
|
346
|
+
if (mockStorage) {
|
|
347
|
+
await webex.boundedStorage.put(
|
|
348
|
+
'Reachability',
|
|
349
|
+
'reachability.result',
|
|
350
|
+
JSON.stringify(mockStorage)
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
const reachability = new Reachability(webex);
|
|
354
|
+
|
|
355
|
+
const result = await reachability.getReachabilityResults();
|
|
356
|
+
|
|
357
|
+
assert.deepEqual(result, expectedResult);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
it('returns undefined if reading from local storage fails', async () => {
|
|
361
|
+
sinon.stub(webex.boundedStorage, 'get').rejects(new Error('fake error'));
|
|
362
|
+
|
|
363
|
+
const reachability = new Reachability(webex);
|
|
364
|
+
|
|
365
|
+
const result = await reachability.getReachabilityResults();
|
|
366
|
+
|
|
367
|
+
assert.isUndefined(result);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('returns results from local storage, converted to the backend data format', async () => {
|
|
371
|
+
await runCheck(
|
|
372
|
+
// mock storage:
|
|
373
|
+
{
|
|
374
|
+
cluster1: {
|
|
375
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
376
|
+
tcp: {result: 'unreachable'},
|
|
377
|
+
xtls: {result: 'untested'},
|
|
378
|
+
},
|
|
379
|
+
cluster2: {
|
|
380
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200},
|
|
381
|
+
tcp: {result: 'unreachable'},
|
|
382
|
+
xtls: {result: 'untested'},
|
|
383
|
+
isVideoMesh: true,
|
|
384
|
+
},
|
|
385
|
+
cluster3: {
|
|
386
|
+
udp: {result: 'unreachable'},
|
|
387
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
388
|
+
xtls: {result: 'untested'},
|
|
389
|
+
isVideoMesh: true,
|
|
390
|
+
someOtherField: 'any value',
|
|
391
|
+
},
|
|
392
|
+
cluster4: {
|
|
393
|
+
udp: {result: 'reachable', latencyInMilliseconds: 300},
|
|
394
|
+
tcp: {result: 'untested'},
|
|
395
|
+
xtls: {result: 'untested'},
|
|
396
|
+
someOtherField: 'any value',
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
// expected result (same as above, but with values converted and isVideoMesh and someOtherField stripped out):
|
|
400
|
+
{
|
|
401
|
+
cluster1: {
|
|
402
|
+
udp: {reachable: 'true', latencyInMilliseconds: '100'},
|
|
403
|
+
tcp: {reachable: 'false'},
|
|
404
|
+
xtls: {untested: 'true'},
|
|
405
|
+
},
|
|
406
|
+
cluster2: {
|
|
407
|
+
udp: {reachable: 'true', latencyInMilliseconds: '200'},
|
|
408
|
+
tcp: {reachable: 'false'},
|
|
409
|
+
xtls: {untested: 'true'},
|
|
410
|
+
},
|
|
411
|
+
cluster3: {
|
|
412
|
+
udp: {reachable: 'false'},
|
|
413
|
+
tcp: {reachable: 'true', latencyInMilliseconds: '100', clientMediaIPs: ['10.10.10.10']},
|
|
414
|
+
xtls: {untested: 'true'},
|
|
415
|
+
},
|
|
416
|
+
cluster4: {
|
|
417
|
+
udp: {reachable: 'true', latencyInMilliseconds: '300'},
|
|
418
|
+
tcp: {untested: 'true'},
|
|
419
|
+
xtls: {untested: 'true'},
|
|
420
|
+
},
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
describe('getReachabilityMetrics', () => {
|
|
427
|
+
let webex;
|
|
428
|
+
|
|
429
|
+
beforeEach(() => {
|
|
430
|
+
webex = new MockWebex();
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
afterEach(() => {
|
|
434
|
+
sinon.restore();
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
const runCheck = async (mockStorage: any, expectedResult: any) => {
|
|
438
|
+
if (mockStorage) {
|
|
439
|
+
await webex.boundedStorage.put(
|
|
440
|
+
'Reachability',
|
|
441
|
+
'reachability.result',
|
|
442
|
+
JSON.stringify(mockStorage)
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
const reachability = new Reachability(webex);
|
|
446
|
+
const result = await reachability.getReachabilityMetrics();
|
|
447
|
+
|
|
448
|
+
assert.deepEqual(result, expectedResult);
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
it('returns all zeros if reading from local storage fails', async () => {
|
|
452
|
+
sinon.stub(webex.boundedStorage, 'get').rejects(new Error('fake error'));
|
|
453
|
+
|
|
454
|
+
const reachability = new Reachability(webex);
|
|
455
|
+
|
|
456
|
+
const result = await reachability.getReachabilityMetrics();
|
|
457
|
+
|
|
458
|
+
assert.deepEqual(result, {
|
|
459
|
+
reachability_public_udp_success: 0,
|
|
460
|
+
reachability_public_udp_failed: 0,
|
|
461
|
+
reachability_public_tcp_success: 0,
|
|
462
|
+
reachability_public_tcp_failed: 0,
|
|
463
|
+
reachability_vmn_udp_success: 0,
|
|
464
|
+
reachability_vmn_udp_failed: 0,
|
|
465
|
+
reachability_vmn_tcp_success: 0,
|
|
466
|
+
reachability_vmn_tcp_failed: 0,
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('returns correct stats based on local storage results', async () => {
|
|
471
|
+
await runCheck(
|
|
472
|
+
// mock storage:
|
|
473
|
+
{
|
|
474
|
+
public1: {
|
|
475
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
476
|
+
tcp: {result: 'untested'},
|
|
477
|
+
xtls: {result: 'untested'},
|
|
478
|
+
},
|
|
479
|
+
vmn1: {
|
|
480
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200},
|
|
481
|
+
tcp: {result: 'unreachable'},
|
|
482
|
+
xtls: {result: 'untested'},
|
|
483
|
+
isVideoMesh: true,
|
|
484
|
+
},
|
|
485
|
+
vmn2: {
|
|
486
|
+
udp: {result: 'untested'},
|
|
487
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
488
|
+
xtls: {result: 'untested'},
|
|
489
|
+
isVideoMesh: true,
|
|
490
|
+
someOtherField: 'any value',
|
|
491
|
+
},
|
|
492
|
+
public2: {
|
|
493
|
+
udp: {result: 'unreachable'},
|
|
494
|
+
tcp: {result: 'unreachable'},
|
|
495
|
+
xtls: {result: 'untested'},
|
|
496
|
+
someOtherField: 'any value',
|
|
497
|
+
},
|
|
498
|
+
public3: {
|
|
499
|
+
udp: {result: 'reachable', latencyInMilliseconds: 400, clientMediaIPs: ['10.10.10.10']},
|
|
500
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
501
|
+
xtls: {result: 'untested'},
|
|
502
|
+
isVideoMesh: false,
|
|
503
|
+
someOtherField: 'any value',
|
|
504
|
+
},
|
|
505
|
+
public4: {
|
|
506
|
+
udp: {result: 'reachable', latencyInMilliseconds: 40, clientMediaIPs: ['10.10.10.11']},
|
|
507
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.11']},
|
|
508
|
+
xtls: {result: 'untested'},
|
|
509
|
+
isVideoMesh: false,
|
|
510
|
+
someOtherField: 'any value',
|
|
511
|
+
},
|
|
512
|
+
public5: {
|
|
513
|
+
udp: {result: 'unreachable'},
|
|
514
|
+
tcp: {result: 'untested'},
|
|
515
|
+
xtls: {result: 'untested'},
|
|
516
|
+
isVideoMesh: false,
|
|
517
|
+
someOtherField: 'any value',
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
// expected result:
|
|
521
|
+
{
|
|
522
|
+
reachability_public_udp_success: 3,
|
|
523
|
+
reachability_public_udp_failed: 2,
|
|
524
|
+
reachability_public_tcp_success: 2,
|
|
525
|
+
reachability_public_tcp_failed: 1,
|
|
526
|
+
reachability_vmn_udp_success: 1,
|
|
527
|
+
reachability_vmn_udp_failed: 0,
|
|
528
|
+
reachability_vmn_tcp_success: 1,
|
|
529
|
+
reachability_vmn_tcp_failed: 1,
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('returns correct stats when only public nodes were tested', async () => {
|
|
535
|
+
await runCheck(
|
|
536
|
+
// mock storage:
|
|
537
|
+
{
|
|
538
|
+
public1: {
|
|
539
|
+
udp: {result: 'reachable', latencyInMilliseconds: 400, clientMediaIPs: ['10.10.10.10']},
|
|
540
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
541
|
+
xtls: {result: 'untested'},
|
|
542
|
+
isVideoMesh: false,
|
|
543
|
+
},
|
|
544
|
+
public2: {
|
|
545
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
546
|
+
tcp: {result: 'untested'},
|
|
547
|
+
xtls: {result: 'untested'},
|
|
548
|
+
},
|
|
549
|
+
public3: {
|
|
550
|
+
udp: {result: 'unreachable'},
|
|
551
|
+
tcp: {result: 'unreachable'},
|
|
552
|
+
xtls: {result: 'untested'},
|
|
553
|
+
someOtherField: 'any value',
|
|
554
|
+
},
|
|
555
|
+
public4: {
|
|
556
|
+
udp: {result: 'untested'},
|
|
557
|
+
tcp: {result: 'unreachable'},
|
|
558
|
+
xtls: {result: 'untested'},
|
|
559
|
+
isVideoMesh: false,
|
|
560
|
+
someOtherField: 'any value',
|
|
561
|
+
},
|
|
562
|
+
public5: {
|
|
563
|
+
udp: {result: 'reachable', latencyInMilliseconds: '400', clientMediaIPs: ['10.10.10.10']},
|
|
564
|
+
tcp: {result: 'untested'},
|
|
565
|
+
xtls: {result: 'untested'},
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
// expected result:
|
|
569
|
+
{
|
|
570
|
+
reachability_public_udp_success: 3,
|
|
571
|
+
reachability_public_udp_failed: 1,
|
|
572
|
+
reachability_public_tcp_success: 1,
|
|
573
|
+
reachability_public_tcp_failed: 2,
|
|
574
|
+
reachability_vmn_udp_success: 0,
|
|
575
|
+
reachability_vmn_udp_failed: 0,
|
|
576
|
+
reachability_vmn_tcp_success: 0,
|
|
577
|
+
reachability_vmn_tcp_failed: 0,
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('returns correct stats when only video mesh nodes were tested', async () => {
|
|
583
|
+
await runCheck(
|
|
584
|
+
// mock storage:
|
|
585
|
+
{
|
|
586
|
+
vmn1: {
|
|
587
|
+
udp: {result: 'unreachable'},
|
|
588
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
589
|
+
xtls: {result: 'untested'},
|
|
590
|
+
isVideoMesh: true,
|
|
591
|
+
},
|
|
592
|
+
vmn2: {
|
|
593
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200, clientMediaIPs: ['10.10.10.10']},
|
|
594
|
+
tcp: {result: 'untested'},
|
|
595
|
+
xtls: {result: 'untested'},
|
|
596
|
+
isVideoMesh: true,
|
|
597
|
+
},
|
|
598
|
+
vmn3: {
|
|
599
|
+
udp: {result: 'reachable', latencyInMilliseconds: 300, clientMediaIPs: ['10.10.10.10']},
|
|
600
|
+
tcp: {result: 'unreachable'},
|
|
601
|
+
xtls: {result: 'untested'},
|
|
602
|
+
isVideoMesh: true,
|
|
603
|
+
},
|
|
604
|
+
vmn4: {
|
|
605
|
+
udp: {result: 'untested'},
|
|
606
|
+
tcp: {result: 'unreachable'},
|
|
607
|
+
xtls: {result: 'untested'},
|
|
608
|
+
isVideoMesh: true,
|
|
609
|
+
someOtherField: 'any value',
|
|
610
|
+
},
|
|
611
|
+
vmn5: {
|
|
612
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200, clientMediaIPs: ['10.10.10.10']},
|
|
613
|
+
tcp: {result: 'unreachable'},
|
|
614
|
+
xtls: {result: 'untested'},
|
|
615
|
+
isVideoMesh: true,
|
|
616
|
+
someOtherField: 'any value',
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
// expected result:
|
|
620
|
+
{
|
|
621
|
+
reachability_public_udp_success: 0,
|
|
622
|
+
reachability_public_udp_failed: 0,
|
|
623
|
+
reachability_public_tcp_success: 0,
|
|
624
|
+
reachability_public_tcp_failed: 0,
|
|
625
|
+
reachability_vmn_udp_success: 3,
|
|
626
|
+
reachability_vmn_udp_failed: 1,
|
|
627
|
+
reachability_vmn_tcp_success: 1,
|
|
628
|
+
reachability_vmn_tcp_failed: 3,
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
});
|
|
632
|
+
});
|