From 515d54094e943abe4fb314ece5fec39b94d9296f Mon Sep 17 00:00:00 2001 From: Andreas Pehrson Date: Mon, 22 Aug 2016 12:01:39 +0200 Subject: [PATCH] Bug 1259788 - Create haveEvents() and friends in head.js. r=jib When we expect multiple events of the same type (in this case "addtrack" on MediaStream) we can use this convenience function to attach a listener and wait for the expected number of events before removing the listener and resolving. This also adds a function to check that there were no extra events of the same kind after the expected N events, and a function that checks that we don't see a certain event within a given timeout period. MozReview-Commit-ID: 1P8MkEI0Yzm --HG-- extra : rebase_source : a815d5834c71785359613c2fb5af3cdb14ba1a54 --- dom/media/tests/mochitest/head.js | 77 +++++++++++++++++-- ...onnection_addtrack_removetrack_events.html | 6 +- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/dom/media/tests/mochitest/head.js b/dom/media/tests/mochitest/head.js index d0c1e7befde2..8b5b96feb6db 100644 --- a/dom/media/tests/mochitest/head.js +++ b/dom/media/tests/mochitest/head.js @@ -591,6 +591,33 @@ function createOneShotEventWrapper(wrapper, obj, event) { }; } +/** + * Returns a promise that resolves when `target` has raised an event with the + * given name the given number of times. Cancel the returned promise by passing + * in a `cancelPromise` and resolve it. + * + * @param {object} target + * The target on which the event should occur. + * @param {string} name + * The name of the event that should occur. + * @param {integer} count + * Optional number of times the event should be raised before resolving. + * @param {promise} cancelPromise + * Optional promise that on resolving rejects the returned promise, + * so we can avoid logging results after a test has finished. + * @returns {promise} A promise that resolves to the last of the seen events. + */ +function haveEvents(target, name, count, cancelPromise) { + var listener; + var counter = count || 1; + return Promise.race([ + (cancelPromise || new Promise(() => {})).then(e => Promise.reject(e)), + new Promise(resolve => + target.addEventListener(name, listener = e => (--counter < 1 && resolve(e)))) + ]) + .then(e => (target.removeEventListener(name, listener), e)); +}; + /** * Returns a promise that resolves when `target` has raised an event with the * given name. Cancel the returned promise by passing in a `cancelPromise` and @@ -601,16 +628,52 @@ function createOneShotEventWrapper(wrapper, obj, event) { * @param {string} name * The name of the event that should occur. * @param {promise} cancelPromise - * A promise that on resolving rejects the returned promise, + * Optional promise that on resolving rejects the returned promise, * so we can avoid logging results after a test has finished. + * @returns {promise} A promise that resolves to the seen event. */ function haveEvent(target, name, cancelPromise) { - var listener; - var p = Promise.race([ - (cancelPromise || new Promise()).then(e => Promise.reject(e)), - new Promise(resolve => target.addEventListener(name, listener = resolve)) - ]); - return p.then(event => (target.removeEventListener(name, listener), event)); + return haveEvents(target, name, 1, cancelPromise); +}; + +/** + * Returns a promise that resolves if the target has not seen the given event + * after one crank (or until the given timeoutPromise resolves) of the event + * loop. + * + * @param {object} target + * The target on which the event should not occur. + * @param {string} name + * The name of the event that should not occur. + * @param {promise} timeoutPromise + * Optional promise defining how long we should wait before resolving. + * @returns {promise} A promise that is rejected if we see the given event, or + * resolves after a timeout otherwise. + */ +function haveNoEvent(target, name, timeoutPromise) { + return haveEvent(target, name, timeoutPromise || wait(0)) + .then(() => Promise.reject(new Error("Too many " + name + " events")), + () => {}); +}; + +/** + * Returns a promise that resolves after the target has seen the given number + * of events but no such event in a following crank of the event loop. + * + * @param {object} target + * The target on which the events should occur. + * @param {string} name + * The name of the event that should occur. + * @param {integer} count + * Optional number of times the event should be raised before resolving. + * @param {promise} cancelPromise + * Optional promise that on resolving rejects the returned promise, + * so we can avoid logging results after a test has finished. + * @returns {promise} A promise that resolves to the last of the seen events. + */ +function haveEventsButNoMore(target, name, count, cancelPromise) { + return haveEvents(target, name, count, cancelPromise) + .then(e => haveNoEvent(target, name).then(() => e)); }; /** diff --git a/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html b/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html index 184b0eacd287..9a45d60d6aea 100644 --- a/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html +++ b/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html @@ -32,7 +32,6 @@ runNetworkTest(function (options) { test.pcLocal.removeSender(videoSenderIndex); test.pcLocal.attachLocalTrack(stream.getTracks()[0], localStream); - let onNextLoop = wait(0); eventsPromise = haveEvent(remoteStream, "addtrack", wait(50000, "No addtrack event")) .then(trackEvent => { ok(trackEvent instanceof MediaStreamTrackEvent, @@ -43,10 +42,7 @@ runNetworkTest(function (options) { is(trackEvent.track.readyState, "live", "added track should be live"); }) - .then(() => haveEvent(remoteStream, "addtrack", onNextLoop) - .then(() => Promise.reject("Unexpected addtrack event for remote stream " + remoteStream.id), - () => Promise.resolve()) - ); + .then(() => haveNoEvent(remoteStream, "addtrack")); remoteStream.addEventListener("removetrack", function onRemovetrack(trackEvent) { ok(false, "UA shouldn't raise 'removetrack' when receiving peer connection");