Bug 1555568: Add RTCPeerConnection-mandatory-getStats.https.html as stats gap analysis metric. r=ng

Differential Revision: https://phabricator.services.mozilla.com/D33120

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan-Ivar Bruaroey 2019-05-30 22:05:40 +00:00
parent cd7a653c08
commit f11e661ca9
2 changed files with 413 additions and 0 deletions

View File

@ -0,0 +1,147 @@
[RTCPeerConnection-mandatory-getStats.https.html]
[RTCRtpStreamStats's transportId]
expected: FAIL
[RTCRtpStreamStats's codecId]
expected: FAIL
[RTCReceivedRtpStreamStats's packetsDiscarded]
expected: FAIL
[RTCInboundRtpStreamStats's trackId]
expected: FAIL
[RTCInboundRtpStreamStats's receiverId]
expected: FAIL
[RTCOutboundRtpStreamStats's trackId]
expected: FAIL
[RTCOutboundRtpStreamStats's senderId]
expected: FAIL
[RTCRemoteOutboundRtpStreamStats's remoteTimestamp]
expected: FAIL
[RTCPeerConnectionStats's dataChannelsOpened]
expected: FAIL
[RTCPeerConnectionStats's dataChannelsClosed]
expected: FAIL
[RTCDataChannelStats's protocol]
expected: FAIL
[RTCDataChannelStats's dataChannelIdentifier]
expected: FAIL
[RTCDataChannelStats's state]
expected: FAIL
[RTCDataChannelStats's messagesSent]
expected: FAIL
[RTCDataChannelStats's bytesSent]
expected: FAIL
[RTCDataChannelStats's messagesReceived]
expected: FAIL
[RTCDataChannelStats's bytesReceived]
expected: FAIL
[RTCMediaStreamStats's streamIdentifer]
expected: FAIL
[RTCMediaStreamStats's trackIds]
expected: FAIL
[RTCMediaHandlerStats's trackIdentifier]
expected: FAIL
[RTCMediaHandlerStats's remoteSource]
expected: FAIL
[RTCMediaHandlerStats's ended]
expected: FAIL
[RTCAudioHandlerStats's audioLevel]
expected: FAIL
[RTCVideoHandlerStats's frameWidth]
expected: FAIL
[RTCVideoHandlerStats's frameHeight]
expected: FAIL
[RTCVideoHandlerStats's framesPerSecond]
expected: FAIL
[RTCVideoSenderStats's framesSent]
expected: FAIL
[RTCVideoReceiverStats's framesReceived]
expected: FAIL
[RTCVideoReceiverStats's framesDecoded]
expected: FAIL
[RTCVideoReceiverStats's framesDropped]
expected: FAIL
[RTCVideoReceiverStats's partialFramesLost]
expected: FAIL
[RTCCodecStats's payloadType]
expected: FAIL
[RTCCodecStats's codecType]
expected: FAIL
[RTCCodecStats's clockRate]
expected: FAIL
[RTCCodecStats's channels]
expected: FAIL
[RTCCodecStats's sdpFmtpLine]
expected: FAIL
[RTCTransportStats's bytesSent]
expected: FAIL
[RTCTransportStats's bytesReceived]
expected: FAIL
[RTCTransportStats's rtcpTransportStatsId]
expected: FAIL
[RTCTransportStats's selectedCandidatePairId]
expected: FAIL
[RTCTransportStats's localCertificateId]
expected: FAIL
[RTCTransportStats's remoteCertificateId]
expected: FAIL
[RTCIceCandidatePairStats's totalRoundTripTime]
expected: FAIL
[RTCIceCandidatePairStats's currentRoundTripTime]
expected: FAIL
[RTCIceCandidateStats's url]
expected: FAIL
[RTCCertificateStats's fingerprint]
expected: FAIL
[RTCCertificateStats's fingerprintAlgorithm]
expected: FAIL
[RTCCertificateStats's base64Certificate]
expected: FAIL
[RTCCertificateStats's issuerCertificateId]
expected: FAIL

View File

@ -0,0 +1,266 @@
<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title>Mandatory-to-implement stats compliance (a subset of webrtc-stats)</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="RTCPeerConnection-helper.js"></script>
<script src="dictionary-helper.js"></script>
<script src="RTCStats-helper.js"></script>
<script>
'use strict';
// From https://w3c.github.io/webrtc-pc/#mandatory-to-implement-stats
const mandatory = {
RTCRtpStreamStats: [
"ssrc",
"kind",
"transportId",
"codecId",
],
RTCReceivedRtpStreamStats: [
"packetsReceived",
"packetsLost",
"jitter",
"packetsDiscarded",
],
RTCInboundRtpStreamStats: [
"trackId",
"receiverId",
"remoteId",
"framesDecoded",
],
RTCRemoteInboundRtpStreamStats: [
"localId",
"roundTripTime",
],
RTCSentRtpStreamStats: [
"packetsSent",
"bytesSent"
],
RTCOutboundRtpStreamStats: [
"trackId",
"senderId",
"remoteId",
"framesEncoded",
],
RTCRemoteOutboundRtpStreamStats: [
"localId",
"remoteTimestamp",
],
RTCPeerConnectionStats: [
"dataChannelsOpened",
"dataChannelsClosed",
],
RTCDataChannelStats: [
"protocol",
"dataChannelIdentifier",
"state",
"messagesSent",
"bytesSent",
"messagesReceived",
"bytesReceived",
],
RTCMediaStreamStats: [
"streamIdentifer",
"trackIds",
],
RTCMediaHandlerStats: [
"trackIdentifier",
"remoteSource",
"ended",
],
RTCAudioHandlerStats: [
"audioLevel",
],
RTCVideoHandlerStats: [
"frameWidth",
"frameHeight",
"framesPerSecond",
],
RTCVideoSenderStats: [
"framesSent",
],
RTCVideoReceiverStats: [
"framesReceived",
"framesDecoded",
"framesDropped",
"partialFramesLost",
],
RTCCodecStats: [
"payloadType",
"codecType",
"clockRate",
"channels",
"sdpFmtpLine",
],
RTCTransportStats: [
"bytesSent",
"bytesReceived",
"rtcpTransportStatsId",
"selectedCandidatePairId",
"localCertificateId",
"remoteCertificateId",
],
RTCIceCandidatePairStats: [
"transportId",
"localCandidateId",
"remoteCandidateId",
"state",
"priority",
"nominated",
"bytesSent",
"bytesReceived",
"totalRoundTripTime",
"currentRoundTripTime",
],
RTCIceCandidateStats: [
"address",
"port",
"protocol",
"candidateType",
"url",
],
RTCCertificateStats: [
"fingerprint",
"fingerprintAlgorithm",
"base64Certificate",
"issuerCertificateId",
],
};
// From https://w3c.github.io/webrtc-stats/webrtc-stats.html#rtcstatstype-str*
const dictionaryNames = {
"codec": "RTCCodecStats",
"inbound-rtp": "RTCInboundRtpStreamStats",
"outbound-rtp": "RTCOutboundRtpStreamStats",
"remote-inbound-rtp": "RTCRemoteInboundRtpStreamStats",
"remote-outbound-rtp": "RTCRemoteOutboundRtpStreamStats",
"csrc": "RTCRtpContributingSourceStats",
"peer-connection": "RTCPeerConnectionStats",
"data-channel": "RTCDataChannelStats",
"stream": "RTCMediaStreamStats",
"track": {
video: "RTCSenderVideoTrackAttachmentStats",
audio: "RTCSenderAudioTrackAttachmentStats"
},
"sender": {
audio: "RTCAudioSenderStats",
video: "RTCVideoSenderStats"
},
"receiver": {
audio: "RTCAudioReceiverStats",
video: "RTCVideoReceiverStats",
},
"transport": "RTCTransportStats",
"candidate-pair": "RTCIceCandidatePairStats",
"local-candidate": "RTCIceCandidateStats",
"remote-candidate": "RTCIceCandidateStats",
"certificate": "RTCCertificateStats",
};
// From https://w3c.github.io/webrtc-stats/webrtc-stats.html (webidl)
const parents = {
RTCVideoHandlerStats: "RTCMediaHandlerStats",
RTCVideoSenderStats: "RTCVideoHandlerStats",
RTCSenderVideoTrackAttachmentStats: "RTCVideoSenderStats",
RTCVideoReceiverStats: "RTCVideoHandlerStats",
RTCAudioHandlerStats: "RTCMediaHandlerStats",
RTCAudioSenderStats: "RTCAudioHandlerStats",
RTCSenderAudioTrackAttachmentStats: "RTCAudioSenderStats",
RTCAudioReceiverStats: "RTCAudioHandlerStats",
RTCReceivedRtpStreamStats: "RTCRtpStreamStats",
RTCInboundRtpStreamStats: "RTCReceivedRtpStreamStats",
RTCRemoteInboundRtpStreamStats: "RTCReceivedRtpStreamStats",
RTCSentRtpStreamStats: "RTCRtpStreamStats",
RTCOutboundRtpStreamStats: "RTCSentRtpStreamStats",
RTCRemoteOutboundRtpStreamStats : "RTCSentRtpStreamStats",
};
const remaining = JSON.parse(JSON.stringify(mandatory));
for (const dictName in remaining) {
remaining[dictName] = new Set(remaining[dictName]);
}
async function getAllStats(t, pc) {
// Try to obtain as many stats as possible, waiting up to 20 seconds for
// roundTripTime which can take several RTCP messages to calculate.
let stats;
for (let i = 0; i < 20; i++) {
stats = await pc.getStats();
const values = [...stats.values()];
const [audio, video] = ["audio", "video"].map(kind =>
values.find(s => s.type == "remote-inbound-rtp" && s.kind == kind));
if (audio && "roundTripTime" in audio &&
video && "roundTripTime" in video) {
return stats;
}
await new Promise(r => t.step_timeout(r, 1000));
}
return stats;
}
let succeed;
const success = new Promise(r => succeed = r);
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());
pc1.createDataChannel("dummy", {negotiated: true, id: 0});
pc2.createDataChannel("dummy", {negotiated: true, id: 0});
const stream = await getNoiseStream({video: true, audio:true});
for (const track of stream.getTracks()) {
pc1.addTrack(track, stream);
pc2.addTrack(track, stream);
t.add_cleanup(() => track.stop());
}
exchangeIceCandidates(pc1, pc2);
await doSignalingHandshake(pc1, pc2);
const stats = await getAllStats(t, pc1);
// The focus of this test is not API correctness, but rather to provide an
// accessible metric of implementation progress by dictionary member. We count
// whether we've seen each dictionary's mandatory members in getStats().
for (const stat of stats.values()) {
let dictName = dictionaryNames[stat.type];
if (!dictName) continue;
if (typeof dictName == "object") {
dictName = dictName[stat.kind];
}
assert_equals(typeof dictName, "string", "Test error. String.");
if (dictName && mandatory[dictName]) {
do {
const memberNames = mandatory[dictName];
const remainingNames = remaining[dictName];
assert_true(memberNames.length > 0, "Test error. Parent not found.");
for (const memberName of memberNames) {
if (memberName in stat) {
assert_not_equals(stat[memberName], undefined, "Not undefined");
remainingNames.delete(memberName);
}
}
dictName = parents[dictName];
} while (dictName);
}
}
succeed();
}, 'getStats succeeds');
for (const dictName in mandatory) {
for (const memberName of mandatory[dictName]) {
promise_test(async t => {
await success;
assert_true(!remaining[dictName].has(memberName),
`Is ${memberName} present`);
}, `${dictName}'s ${memberName}`);
}
}
</script>