Bug 1425621 - Part 1: Test-case for removeTrack and MediaStream.onremovetrack. r=jib
authorByron Campen [:bwc] <docfaraday@gmail.com>
Mon, 18 Dec 2017 14:37:43 -0600
changeset 453412 ecc116e85fb208529894051ae2c0d7f0420151b2
parent 453411 eb8c89d823a6036963332c14e878ff48292c5915
child 453413 eb93d67c574758aea9936e5be6117bd2af3a3573
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib
bugs1425621
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1425621 - Part 1: Test-case for removeTrack and MediaStream.onremovetrack. r=jib Also, expects onmute to happen before SRD resolves, even for offers. MozReview-Commit-ID: 2ibQKDfyHYH
dom/media/tests/mochitest/test_peerConnection_transceivers.html
--- a/dom/media/tests/mochitest/test_peerConnection_transceivers.html
+++ b/dom/media/tests/mochitest/test_peerConnection_transceivers.html
@@ -36,16 +36,34 @@
     let finishCollecting = () => {
       target.removeEventListener(name, handler);
       return events;
     };
 
     return {finish: finishCollecting};
   };
 
+  let collectAddTrackEvents = stream => {
+    let checkEvent = e => {
+      ok(e.track, "Track is set on event");
+      ok(stream.getTracks().includes(e.track),
+        "track in addtrack event is in the stream");
+    };
+    return collectEvents(stream, "addtrack", checkEvent);
+  };
+
+  let collectRemoveTrackEvents = stream => {
+    let checkEvent = e => {
+      ok(e.track, "Track is set on event");
+      ok(!stream.getTracks().includes(e.track),
+        "track in removetrack event is not in the stream");
+    };
+    return collectEvents(stream, "removetrack", checkEvent);
+  };
+
   let collectTrackEvents = pc => {
     let checkEvent = e => {
       ok(e.track, "Track is set on event");
       ok(e.receiver, "Receiver is set on event");
       ok(e.transceiver, "Transceiver is set on event");
       ok(e.streams, "Streams is set on event");
       e.streams.forEach(stream => {
         ok(stream.getTracks().includes(e.track),
@@ -762,16 +780,137 @@
         {currentDirection: "sendrecv"}
       ]);
 
     pc1.close();
     pc2.close();
     stopTracks(stream);
   };
 
+  let checkRemoveTrackNegotiation = async () => {
+    let pc1 = new RTCPeerConnection();
+    let pc2 = new RTCPeerConnection();
+    let stream = await getUserMedia({audio: true, video: true});
+    let audio = stream.getAudioTracks()[0];
+    pc1.addTrack(audio, stream);
+    let video = stream.getVideoTracks()[0];
+    pc1.addTrack(video, stream);
+    // We want both a sendrecv and sendonly transceiver to test that the
+    // appropriate direction changes happen.
+    pc1.getTransceivers()[1].direction = "sendonly";
+
+    let offer = await pc1.createOffer();
+
+    // Get a reference to the stream
+    let trackEventCollector = collectTrackEvents(pc2);
+    await pc2.setRemoteDescription(offer);
+    let pc2TrackEvents = trackEventCollector.finish();
+    hasProps(pc2TrackEvents,
+      [
+        {streams: [{id: stream.id}]},
+        {streams: [{id: stream.id}]}
+      ]);
+    let receiveStream = pc2TrackEvents[0].streams[0];
+
+    // Verify that rollback causes onremovetrack to fire for the added tracks
+    let removetrackEventCollector = collectRemoveTrackEvents(receiveStream);
+    await pc2.setRemoteDescription({type: "rollback"});
+    let removedtracks = removetrackEventCollector.finish().map(e => e.track);
+    is(removedtracks.length, 2, "Rollback should have removed two tracks");
+    ok(removedtracks.includes(pc2TrackEvents[0].track), "First track should be removed");
+    ok(removedtracks.includes(pc2TrackEvents[1].track), "Second track should be removed");
+
+    offer = await pc1.createOffer();
+
+    let addtrackEventCollector = collectAddTrackEvents(receiveStream);
+    trackEventCollector = collectTrackEvents(pc2);
+    await pc2.setRemoteDescription(offer);
+    pc2TrackEvents = trackEventCollector.finish();
+    let addedtracks = addtrackEventCollector.finish().map(e => e.track);
+    is(addedtracks.length, 2,
+      "pc2.setRemoteDescription(offer) should have added two tracks to the receive stream");
+    ok(addedtracks.includes(pc2TrackEvents[0].track), "First track should be added");
+    ok(addedtracks.includes(pc2TrackEvents[1].track), "Second track should be added");
+
+    await pc1.setLocalDescription(offer);
+    let answer = await pc2.createAnswer();
+    await pc1.setRemoteDescription(answer);
+    await pc2.setLocalDescription(answer);
+    pc1.removeTrack(pc1.getSenders()[0]);
+
+    hasProps(pc1.getTransceivers(),
+      [
+        {
+          sender: {track: null},
+          direction: "recvonly"
+        },
+        {
+          sender: {track: video},
+          direction: "sendonly"
+        }
+      ]);
+
+    await negotiationNeeded(pc1);
+
+    pc1.removeTrack(pc1.getSenders()[1]);
+
+    hasProps(pc1.getTransceivers(),
+      [
+        {
+          sender: {track: null},
+          direction: "recvonly"
+        },
+        {
+          sender: {track: null},
+          direction: "inactive"
+        }
+      ]);
+
+    // pc1 as offerer
+    offer = await pc1.createOffer();
+
+    removetrackEventCollector = collectRemoveTrackEvents(receiveStream);
+    await pc2.setRemoteDescription(offer);
+    removedtracks = removetrackEventCollector.finish().map(e => e.track);
+    is(removedtracks.length, 2, "Should have two removed tracks");
+    ok(removedtracks.includes(pc2TrackEvents[0].track), "First track should be removed");
+    ok(removedtracks.includes(pc2TrackEvents[1].track), "Second track should be removed");
+
+    addtrackEventCollector = collectAddTrackEvents(receiveStream);
+    await pc2.setRemoteDescription({type: "rollback"});
+    addedtracks = addtrackEventCollector.finish().map(e => e.track);
+    is(addedtracks.length, 2, "Rollback should have added two tracks");
+
+    // pc2 as offerer
+    offer = await pc2.createOffer();
+    await pc2.setLocalDescription(offer);
+    await pc1.setRemoteDescription(offer);
+    answer = await pc1.createAnswer();
+    await pc1.setLocalDescription(answer);
+
+    removetrackEventCollector = collectRemoveTrackEvents(receiveStream);
+    await pc2.setRemoteDescription(answer);
+    removedtracks = removetrackEventCollector.finish().map(e => e.track);
+    is(removedtracks.length, 2, "Should have two removed tracks");
+
+    hasProps(pc2.getTransceivers(),
+      [
+        {
+          currentDirection: "inactive"
+        },
+        {
+          currentDirection: "inactive"
+        }
+      ]);
+
+    pc1.close();
+    pc2.close();
+    stopTracks(stream);
+  };
+
   let checkSetDirection = async () => {
     let pc = new RTCPeerConnection();
     pc.addTransceiver("audio");
 
     pc.getTransceivers()[0].direction = "sendonly";
     hasProps(pc.getTransceivers(),[{direction: "sendonly"}]);
     pc.getTransceivers()[0].direction = "recvonly";
     hasProps(pc.getTransceivers(),[{direction: "recvonly"}]);
@@ -1031,25 +1170,25 @@
     await pc2.setLocalDescription(answer);
     await gotMuteAudio1;
     await gotMuteVideo1;
 
     // Check whether disabling on remote causes onmute
     pc1.getTransceivers()[0].direction = "inactive";
     pc1.getTransceivers()[1].direction = "inactive";
     offer = await pc1.createOffer();
-    await pc2.setRemoteDescription(offer);
-    await pc1.setLocalDescription(offer);
-    answer = await pc2.createAnswer();
     let gotMuteAudio2 = gotMuteEvent(pc2.getTransceivers()[0].receiver.track);
     let gotMuteVideo2 = gotMuteEvent(pc2.getTransceivers()[1].receiver.track);
+    await pc2.setRemoteDescription(offer);
+    await gotMuteAudio2;
+    await gotMuteVideo2;
+    await pc1.setLocalDescription(offer);
+    answer = await pc2.createAnswer();
     await pc1.setRemoteDescription(answer);
     await pc2.setLocalDescription(answer);
-    await gotMuteAudio2;
-    await gotMuteVideo2;
 
     // Check whether onunmute fires when we turn everything on again
     pc1.getTransceivers()[0].direction = "sendrecv";
     pc1.getTransceivers()[1].direction = "sendrecv";
     offer = await pc1.createOffer();
     await pc2.setRemoteDescription(offer);
     await pc1.setLocalDescription(offer);
     answer = await pc2.createAnswer();
@@ -2054,16 +2193,17 @@
     await checkSendrecvWithTracklessStream();
     await checkAddTransceiverNoTrackDoesntPair();
     await checkAddTransceiverWithTrackDoesntPair();
     await checkAddTransceiverThenReplaceTrackDoesntPair();
     await checkAddTransceiverThenAddTrackPairs();
     await checkAddTrackPairs();
     await checkReplaceTrackNullDoesntPreventPairing();
     await checkRemoveAndReadd();
+    await checkRemoveTrackNegotiation();
     await checkMute();
     await checkOnAddStream();
     await checkStop();
     await checkStopAfterCreateOffer();
     await checkStopAfterSetLocalOffer();
     await checkStopAfterSetRemoteOffer();
     await checkStopAfterCreateAnswer();
     await checkStopAfterSetLocalAnswer();