Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /webrtc/getstats.html - WPT Dashboard Interop Dashboard
<!doctype html>
<!--
This test uses data only, and thus does not require fake media devices.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>RTCPeerConnection GetStats</title>
</head>
<body>
<div id="log"></div>
<h2>Retrieved stats info</h2>
<pre>
<input type="button" onclick="showStats()" value="Show stats"></input>
<div id="stats">
</div>
</pre>
<!-- These files are in place when executing on W3C. -->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
var test = async_test('Can get stats from a basic WebRTC call.');
var statsToShow;
var gFirstConnection = null;
var gSecondConnection = null;
var onIceCandidateToFirst = test.step_func(function(event) {
gSecondConnection.addIceCandidate(event.candidate);
});
var onIceCandidateToSecond = test.step_func(function(event) {
gFirstConnection.addIceCandidate(event.candidate);
});
var getStatsRecordByType = function(stats, type) {
for (let stat of stats.values()) {
if (stat.type == type) {
return stat;
}
}
return null;
}
var onIceConnectionStateChange = test.step_func(function(event) {
// Wait until connection is established.
// Note - not all browsers reach 'completed' state, so we're
// checking for 'connected' state instead.
if (gFirstConnection.iceConnectionState != 'connected') {
return;
}
gFirstConnection.getStats()
.then(function(report) {
let reportDictionary = {};
for (let stats of report.values()) {
reportDictionary[stats.id] = stats;
}
statsToShow = JSON.stringify(reportDictionary, null, 2);
// Check the stats properties.
assert_not_equals(report, null, 'No report');
let sessionStat = getStatsRecordByType(report, 'peer-connection');
assert_not_equals(sessionStat, null, 'Did not find peer-connection stats');
assert_own_property(sessionStat, 'dataChannelsOpened', 'no dataChannelsOpened stat');
// Once every 4000 or so tests, the datachannel won't be opened when the getStats
// function is done, so allow both 0 and 1 datachannels.
assert_true(sessionStat.dataChannelsOpened == 1 || sessionStat.dataChannelsOpened == 0,
'dataChannelsOpened count wrong');
test.done();
})
.catch(test.step_func(function(e) {
assert_unreached(e.name + ': ' + e.message + ': ');
}));
});
// This function starts the test.
test.step(function() {
gFirstConnection = new RTCPeerConnection(null);
test.add_cleanup(() => gFirstConnection.close());
gFirstConnection.onicecandidate = onIceCandidateToFirst;
gFirstConnection.oniceconnectionstatechange = onIceConnectionStateChange;
gSecondConnection = new RTCPeerConnection(null);
test.add_cleanup(() => gSecondConnection.close());
gSecondConnection.onicecandidate = onIceCandidateToSecond;
// The createDataChannel is necessary and sufficient to make
// sure the ICE connection be attempted.
gFirstConnection.createDataChannel('channel');
var atStep = 'Create offer';
gFirstConnection.createOffer()
.then(function(offer) {
atStep = 'Set local description at first';
return gFirstConnection.setLocalDescription(offer);
})
.then(function() {
atStep = 'Set remote description at second';
return gSecondConnection.setRemoteDescription(
gFirstConnection.localDescription);
})
.then(function() {
atStep = 'Create answer';
return gSecondConnection.createAnswer();
})
.then(function(answer) {
atStep = 'Set local description at second';
return gSecondConnection.setLocalDescription(answer);
})
.then(function() {
atStep = 'Set remote description at first';
return gFirstConnection.setRemoteDescription(
gSecondConnection.localDescription);
})
.catch(test.step_func(function(e) {
assert_unreached('Error ' + e.name + ': ' + e.message +
' happened at step ' + atStep);
}));
});
function showStats() {
// Show the retrieved stats info
var showStats = document.getElementById('stats');
showStats.innerHTML = statsToShow;
}
</script>
</body>
</html>