mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 19:55:39 +00:00
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:
parent
cd7a653c08
commit
f11e661ca9
@ -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
|
@ -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>
|
Loading…
Reference in New Issue
Block a user