Bug 1654430 - Update waitForRtpFlow() mochitest helper to use sender/receiver.getStats. r=ng

Differential Revision: https://phabricator.services.mozilla.com/D89082
This commit is contained in:
Jan-Ivar Bruaroey 2020-09-23 16:09:04 +00:00
Родитель fb585eddf0
Коммит 4c69b0ebaa
3 изменённых файлов: 115 добавлений и 125 удалений

Просмотреть файл

@ -1787,91 +1787,88 @@ PeerConnectionWrapper.prototype = {
* @returns {Promise}
* Returns a promise which yields a StatsReport object with RTP stats.
*/
async waitForRtpFlow(track) {
info("waitForRtpFlow(" + track.id + ")");
let hasFlow = (stats, retries) => {
const dict = JSON.stringify([...stats.entries()]);
info(
`Checking for stats in ${dict} for ${track.kind} track ${track.id}` +
`retry number ${retries}`
);
const rtp = [...stats.values()].find(({ type }) =>
["inbound-rtp", "outbound-rtp"].includes(type)
);
if (!rtp) {
return false;
}
info("Should have RTP stats for track " + track.id);
info("RTP stats: " + JSON.stringify(rtp));
let nrPackets =
rtp[rtp.type == "outbound-rtp" ? "packetsSent" : "packetsReceived"];
info(
"Track " +
track.id +
" has " +
nrPackets +
" " +
rtp.type +
" RTP packets."
);
return nrPackets > 0;
};
async _waitForRtpFlow(target, rtpType) {
const { track } = target;
info(`_waitForRtpFlow(${track.id}, ${rtpType})`);
const packets = `packets${rtpType == "outbound-rtp" ? "Sent" : "Received"}`;
// Time between stats checks
const retryInterval = 500;
// Timeout in ms
const timeout = 30000;
let retry = 0;
// Check hasFlow at a reasonable interval
for (let remaining = timeout; remaining >= 0; remaining -= retryInterval) {
let stats = await this._pc.getStats(track);
if (hasFlow(stats, retry++)) {
ok(true, "RTP flowing for " + track.kind + " track " + track.id);
return stats;
const retryInterval = 500; // Time between stats checks
const timeout = 30000; // Timeout in ms
const retries = timeout / retryInterval;
for (let i = 0; i < retries; i++) {
info(`Checking ${rtpType} for ${track.kind} track ${track.id} try ${i}`);
for (const rtp of (await target.getStats()).values()) {
if (rtp.type != rtpType) {
continue;
}
if (rtp.kind != track.kind) {
continue;
}
const numPackets = rtp[packets];
info(`Track ${track.id} has ${numPackets} ${packets}.`);
if (!numPackets) {
continue;
}
ok(true, `RTP flowing for ${track.kind} track ${track.id}`);
return;
}
await wait(retryInterval);
}
throw new Error(
"Timeout checking for stats for track " +
track.id +
" after at least" +
timeout +
"ms"
`Checking stats for track ${track.id} timed out after ${timeout} ms`
);
},
getExpectedActiveReceiveTracks() {
/**
* Wait for inbound RTP packet flow for the given MediaStreamTrack.
*
* @param {object} receiver
* An RTCRtpReceiver to wait for data flow on.
* @returns {Promise}
* Returns a promise that resolves once data is flowing.
*/
async waitForInboundRtpFlow(receiver) {
return this._waitForRtpFlow(receiver, "inbound-rtp");
},
/**
* Wait for outbound RTP packet flow for the given MediaStreamTrack.
*
* @param {object} sender
* An RTCRtpSender to wait for data flow on.
* @returns {Promise}
* Returns a promise that resolves once data is flowing.
*/
async waitForOutboundRtpFlow(sender) {
return this._waitForRtpFlow(sender, "outbound-rtp");
},
getExpectedActiveReceivers() {
return this._pc
.getTransceivers()
.filter(t => {
return (
.filter(
t =>
!t.stopped &&
t.currentDirection &&
t.currentDirection != "inactive" &&
t.currentDirection != "sendonly"
);
})
.map(t => {
)
.filter(({ receiver }) => receiver.track)
.map(({ mid, currentDirection, receiver }) => {
info(
"Found transceiver that should be receiving RTP: mid=" +
t.mid +
" currentDirection=" +
t.currentDirection +
" kind=" +
t.receiver.track.kind +
" track-id=" +
t.receiver.track.id
`Found transceiver that should be receiving RTP: mid=${mid}` +
` currentDirection=${currentDirection}` +
` kind=${receiver.track.kind} track-id=${receiver.track.id}`
);
return t.receiver.track;
})
.filter(t => t);
return receiver;
});
},
getExpectedSendTracks() {
return this._pc
.getSenders()
.map(s => s.track)
.filter(t => t);
getExpectedSenders() {
return this._pc.getSenders().filter(({ track }) => track);
},
/**
@ -1882,24 +1879,21 @@ PeerConnectionWrapper.prototype = {
* A promise that resolves when media flows for all elements and tracks
*/
waitForMediaFlow() {
return Promise.all(
[].concat(
this.localMediaElements.map(element =>
this.waitForMediaElementFlow(element)
),
this.remoteMediaElements
.filter(elem =>
this.getExpectedActiveReceiveTracks().some(track =>
elem.srcObject.getTracks().some(t => t == track)
)
const receivers = this.getExpectedActiveReceivers();
return Promise.all([
...this.localMediaElements.map(el => this.waitForMediaElementFlow(el)),
...this.remoteMediaElements
.filter(({ srcObject }) =>
receivers.some(({ track }) =>
srcObject.getTracks().some(t => t == track)
)
.map(elem => this.waitForMediaElementFlow(elem)),
this.getExpectedActiveReceiveTracks().map(track =>
this.waitForRtpFlow(track)
),
this.getExpectedSendTracks().map(track => this.waitForRtpFlow(track))
)
);
)
.map(el => this.waitForMediaElementFlow(el)),
...receivers.map(receiver => this.waitForInboundRtpFlow(receiver)),
...this.getExpectedSenders().map(sender =>
this.waitForOutboundRtpFlow(sender)
),
]);
},
async waitForSyncedRtcp() {

Просмотреть файл

@ -153,48 +153,43 @@ function waitForAnIceCandidate(pc) {
});
}
function checkTrackStats(pc, track, outbound) {
var audio = track.kind == "audio";
var msg =
pc +
" stats " +
(outbound ? "outbound " : "inbound ") +
(audio ? "audio" : "video") +
" rtp track id " +
track.id;
return pc.getStats(track).then(stats => {
ok(
pc.hasStat(stats, {
type: outbound ? "outbound-rtp" : "inbound-rtp",
kind: audio ? "audio" : "video",
}),
msg + " - found expected stats"
);
ok(
!pc.hasStat(stats, {
type: outbound ? "inbound-rtp" : "outbound-rtp",
}),
msg + " - did not find extra stats with wrong direction"
);
ok(
!pc.hasStat(stats, {
kind: audio ? "video" : "audio",
}),
msg + " - did not find extra stats with wrong media type"
);
});
async function checkTrackStats(pc, track, outbound) {
const audio = track.kind == "audio";
const msg =
`${pc} stats ${outbound ? "outbound " : "inbound "}` +
`${audio ? "audio" : "video"} rtp track id ${track.id}`;
const stats = await pc.getStats(track);
ok(
pc.hasStat(stats, {
type: outbound ? "outbound-rtp" : "inbound-rtp",
kind: audio ? "audio" : "video",
}),
`${msg} - found expected stats`
);
ok(
!pc.hasStat(stats, {
type: outbound ? "inbound-rtp" : "outbound-rtp",
}),
`${msg} - did not find extra stats with wrong direction`
);
ok(
!pc.hasStat(stats, {
kind: audio ? "video" : "audio",
}),
`${msg} - did not find extra stats with wrong media type`
);
}
var checkAllTrackStats = pc => {
return Promise.all(
[].concat(
pc
.getExpectedActiveReceiveTracks()
.map(track => checkTrackStats(pc, track, false)),
pc.getExpectedSendTracks().map(track => checkTrackStats(pc, track, true))
)
);
};
function checkAllTrackStats(pc) {
return Promise.all([
...pc
.getExpectedActiveReceivers()
.map(({ track }) => checkTrackStats(pc, track, false)),
...pc
.getExpectedSenders()
.map(({ track }) => checkTrackStats(pc, track, true)),
]);
}
// Commands run once at the beginning of each test, even when performing a
// renegotiation test.

Просмотреть файл

@ -1,4 +1,4 @@
<!DOCTYPE HTML>
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
@ -12,6 +12,7 @@
});
runNetworkTest(function (options) {
SimpleTest.requestCompleteLog();
var test = new PeerConnectionTest(options);
test.chain.replace("PC_LOCAL_GUM",
[