blob: 4124963ae43ff616735b74fe175b4b9dd5c3af47 [file] [log] [blame]
Soares Chen0ac9ba42017-07-13 10:08:111<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.getStats</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="RTCPeerConnection-helper.js"></script>
Soares Chen4f92d912017-07-19 05:10:407<script src="dictionary-helper.js"></script>
Soares Chen0ac9ba42017-07-13 10:08:118<script src="RTCStats-helper.js"></script>
9<script>
10 'use strict';
11
12 // Test is based on the following editor draft:
13 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
Soares Chen389b21a2017-07-14 04:54:4414 // https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
15
16 // The following helper function is called from RTCPeerConnection-helper.js
17 // getTrackFromUserMedia
Soares Chen0ac9ba42017-07-13 10:08:1118
Soares Chen4f92d912017-07-19 05:10:4019 // The following helper function is called from RTCStats-helper.js
20 // validateStatsReport
21 // assert_stats_report_has_stats
22
Soares Chen0ac9ba42017-07-13 10:08:1123 /*
24 8.2. RTCPeerConnection Interface Extensions
25 partial interface RTCPeerConnection {
26 Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
27 };
28
29 8.3. RTCStatsReport Object
30 interface RTCStatsReport {
31 readonly maplike<DOMString, object>;
32 };
33
34 8.4. RTCStats Dictionary
35 dictionary RTCStats {
36 DOMHighResTimeStamp timestamp;
37 RTCStatsType type;
38 DOMString id;
39 };
40
41 id
42 Two RTCStats objects, extracted from two different RTCStatsReport objects, MUST
43 have the same id if they were produced by inspecting the same underlying object.
44
45 8.2. getStats
46 1. Let selectorArg be the method's first argument.
47 2. Let connection be the RTCPeerConnection object on which the method was invoked.
48 3. If selectorArg is neither null nor a valid MediaStreamTrack, return a promise
49 rejected with a newly created TypeError.
50 5. Let p be a new promise.
51 6. Run the following steps in parallel:
52 1. Gather the stats indicated by selector according to the stats selection algorithm.
53 2. Resolve p with the resulting RTCStatsReport object, containing the gathered stats.
Soares Chen0ac9ba42017-07-13 10:08:1154 */
55
56 promise_test(() => {
57 const pc = new RTCPeerConnection();
58 return pc.getStats();
59 }, 'getStats() with no argument should succeed');
60
61 promise_test(() => {
62 const pc = new RTCPeerConnection();
63 return pc.getStats(null);
64 }, 'getStats(null) should succeed');
65
66 /*
67 8.2. getStats
68 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
69 member matches selectorArg. If no such sender or receiver exists, return a promise
70 rejected with a newly created InvalidAccessError.
71 */
72 promise_test(t => {
73 const pc = new RTCPeerConnection();
Soares Chen389b21a2017-07-14 04:54:4474 return getTrackFromUserMedia('audio')
75 .then(([track, mediaStream]) => {
Soares Chen0ac9ba42017-07-13 10:08:1176 return promise_rejects(t, 'InvalidAccessError', pc.getStats(track));
77 });
Soares Chen389b21a2017-07-14 04:54:4478 }, 'getStats() with track not added to connection should reject with InvalidAccessError');
Soares Chen0ac9ba42017-07-13 10:08:1179
80 promise_test(t => {
81 const pc = new RTCPeerConnection();
Soares Chen389b21a2017-07-14 04:54:4482 return getTrackFromUserMedia('audio')
83 .then(([track, mediaStream]) => {
Soares Chen0ac9ba42017-07-13 10:08:1184 pc.addTrack(track, mediaStream);
85 return pc.getStats(track);
86 });
Soares Chen389b21a2017-07-14 04:54:4487 }, 'getStats() with track added via addTrack should succeed');
Soares Chen0ac9ba42017-07-13 10:08:1188
89 promise_test(t => {
90 const pc = new RTCPeerConnection();
91 const track = generateMediaStreamTrack();
92 pc.addTransceiver(track);
93
94 return pc.getStats(track);
Soares Chen389b21a2017-07-14 04:54:4495 }, 'getStats() with track added via addTransceiver should succeed');
Soares Chen0ac9ba42017-07-13 10:08:1196
97 /*
98 8.2. getStats
99 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
100 member matches selectorArg. If more than one sender or receiver fit this criteria,
101 return a promise rejected with a newly created InvalidAccessError.
102 */
103 promise_test(t => {
104 const pc = new RTCPeerConnection();
Soares Chen389b21a2017-07-14 04:54:44105 return getTrackFromUserMedia('audio')
106 .then(([track, mediaStream]) => {
107 // addTransceiver allows adding same track multiple times
108 const transceiver1 = pc.addTransceiver(track);
109 const transceiver2 = pc.addTransceiver(track);
110
111 assert_not_equals(transceiver1, transceiver2);
112 assert_not_equals(transciever1.sender, transceiver2.sender);
113 assert_equals(transceiver1.sender.track, transceiver2.sender.track);
114
115 return promise_rejects(t, 'InvalidAccessError', pc.getStats(track));
116 });
117 }, `getStats() with track associated with more than one sender should reject with InvalidAccessError`);
118
119 promise_test(t => {
120 const pc = new RTCPeerConnection();
121 const transceiver1 = pc.addTransceiver('audio');
122
Soares Chen0ac9ba42017-07-13 10:08:11123 // Create another transceiver that resends what
124 // is being received, kind of like echo
Soares Chen389b21a2017-07-14 04:54:44125 const transceiver2 = pc.addTransceiver(transceiver1.receiver.track);
126 assert_equals(transceiver1.receiver.track, transceiver2.sender.track);
Soares Chen0ac9ba42017-07-13 10:08:11127
128 return promise_rejects(t, 'InvalidAccessError', pc.getStats(track));
Soares Chen389b21a2017-07-14 04:54:44129 }, 'getStats() with track associated with both sender and receiver should reject with InvalidAccessError');
Soares Chen0ac9ba42017-07-13 10:08:11130
131 /*
132 8.5. The stats selection algorithm
Soares Chen0ac9ba42017-07-13 10:08:11133 2. If selector is null, gather stats for the whole connection, add them to result,
134 return result, and abort these steps.
Soares Chen0ac9ba42017-07-13 10:08:11135 */
136 promise_test(t => {
137 const pc = new RTCPeerConnection();
138 return pc.getStats()
139 .then(statsReport => {
Soares Chen0ac9ba42017-07-13 10:08:11140 validateStatsReport(statsReport);
Soares Chen389b21a2017-07-14 04:54:44141 assert_stats_report_has_stats(statsReport, ['peer-connection']);
Soares Chen0ac9ba42017-07-13 10:08:11142 });
Soares Chen389b21a2017-07-14 04:54:44143 }, 'getStats() with no argument should return stats report containing peer-connection stats');
Soares Chen0ac9ba42017-07-13 10:08:11144
145 /*
146 8.5. The stats selection algorithm
147 3. If selector is an RTCRtpSender, gather stats for and add the following objects
148 to result:
149 - All RTCOutboundRTPStreamStats objects corresponding to selector.
150 - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats
151 objects added.
152 */
153 promise_test(() => {
154 const pc = new RTCPeerConnection();
Soares Chen389b21a2017-07-14 04:54:44155 return getTrackFromUserMedia('audio')
156 .then(([track, mediaStream]) => {
Soares Chen0ac9ba42017-07-13 10:08:11157 pc.addTrack(track, mediaStream);
158
159 return pc.getStats(track)
160 .then(statsReport => {
Soares Chen0ac9ba42017-07-13 10:08:11161 validateStatsReport(statsReport);
Soares Chen389b21a2017-07-14 04:54:44162 assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
Soares Chen0ac9ba42017-07-13 10:08:11163 });
164 });
Soares Chen389b21a2017-07-14 04:54:44165 }, `getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats`);
166
167
168 /*
169 8.5. The stats selection algorithm
170 4. If selector is an RTCRtpReceiver, gather stats for and add the following objects
171 to result:
172 - All RTCInboundRTPStreamStats objects corresponding to selector.
173 - All stats objects referenced directly or indirectly by the RTCInboundRTPStreamStats
174 added.
175 */
176 promise_test(() => {
177 const pc = new RTCPeerConnection();
178 const transceiver = pc.addTransceiver('audio');
179
180 return pc.getStats(transceiver.receiver.track)
181 .then(statsReport => {
182 validateStatsReport(statsReport);
183 assert_stats_report_has_stats(statsReport, ['inbound-rtp']);
184 });
185 }, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats`);
Soares Chen0ac9ba42017-07-13 10:08:11186
187</script>