diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/webrtc/legacy | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webrtc/legacy')
4 files changed, 605 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webrtc/legacy/README.txt b/testing/web-platform/tests/webrtc/legacy/README.txt new file mode 100644 index 0000000000..8adbf6aa17 --- /dev/null +++ b/testing/web-platform/tests/webrtc/legacy/README.txt @@ -0,0 +1,2 @@ +This directory contains files that test for behavior relevant to webrtc, +particularly defined in https://w3c.github.io/webrtc-pc/#legacy-interface-extensions diff --git a/testing/web-platform/tests/webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html b/testing/web-platform/tests/webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html new file mode 100644 index 0000000000..f710498e75 --- /dev/null +++ b/testing/web-platform/tests/webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html @@ -0,0 +1,274 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test legacy offerToReceiveAudio/Video options</title> +<link rel="help" href="https://w3c.github.io/webrtc-pc/#legacy-configuration-extensions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../RTCPeerConnection-helper.js"></script> +<script> + 'use strict'; + + /* + * 4.3.3.2 Configuration data extensions + * partial dictionary RTCOfferOptions + */ + + /* + * offerToReceiveAudio of type boolean + * When this is given a non-false value, no outgoing track of type + * "audio" is attached to the PeerConnection, and the existing + * localDescription (if any) doesn't contain any sendrecv or recv + * audio media sections, createOffer() will behave as if + * addTransceiver("audio") had been called once prior to the createOffer() call. + */ + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer({ offerToReceiveAudio: true }) + .then(offer1 => { + assert_equals(countAudioLine(offer1.sdp), 1, + 'Expect created offer to have audio line'); + + // The first createOffer implicitly calls addTransceiver('audio'), + // so all following offers will also have audio media section + // in their SDP. + return pc.createOffer({ offerToReceiveAudio: false }) + .then(offer2 => { + assert_equals(countAudioLine(offer2.sdp), 1, + 'Expect audio line to remain in created offer'); + }) + }); + }, 'createOffer() with offerToReceiveAudio should add audio line to all subsequent created offers'); + + /* + * offerToReceiveVideo of type boolean + * When this is given a non-false value, and no outgoing track + * of type "video" is attached to the PeerConnection, and the + * existing localDescription (if any) doesn't contain any sendecv + * or recv video media sections, createOffer() will behave as if + * addTransceiver("video") had been called prior to the createOffer() call. + */ + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer({ offerToReceiveVideo: true }) + .then(offer1 => { + assert_equals(countVideoLine(offer1.sdp), 1, + 'Expect created offer to have video line'); + + return pc.createOffer({ offerToReceiveVideo: false }) + .then(offer2 => { + assert_equals(countVideoLine(offer2.sdp), 1, + 'Expect video line to remain in created offer'); + }) + }); + }, 'createOffer() with offerToReceiveVideo should add video line to all subsequent created offers'); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer({ + offerToReceiveAudio: true, + offerToReceiveVideo: false + }).then(offer1 => { + assert_equals(countAudioLine(offer1.sdp), 1, + 'Expect audio line to be found in created offer'); + + assert_equals(countVideoLine(offer1.sdp), 0, + 'Expect video line to not be found in create offer'); + + return pc.createOffer({ + offerToReceiveAudio: false, + offerToReceiveVideo: true + }).then(offer2 => { + assert_equals(countAudioLine(offer2.sdp), 1, + 'Expect audio line to remain in created offer'); + + assert_equals(countVideoLine(offer2.sdp), 1, + 'Expect video line to be found in create offer'); + }) + }); + }, 'createOffer() with offerToReceiveAudio:true, then with offerToReceiveVideo:true, should have result offer with both audio and video line'); + + + // Run some tests for both audio and video kinds + ['audio', 'video'].forEach((kind) => { + const capsKind = kind[0].toUpperCase() + kind.slice(1); + + const offerToReceiveTrue = {}; + offerToReceiveTrue[`offerToReceive${capsKind}`] = true; + + const offerToReceiveFalse = {}; + offerToReceiveFalse[`offerToReceive${capsKind}`] = false; + + // Start testing + promise_test(t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const dummy = pc.createDataChannel('foo'); // Just to have something to offer + + return pc.createOffer(offerToReceiveFalse) + .then(() => { + assert_equals(pc.getTransceivers().length, 0, + 'Expect pc to have no transceivers'); + }); + }, `createOffer() with offerToReceive${capsKind} set to false should not create a transceiver`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer(offerToReceiveTrue) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'recvonly', + 'Expect transceiver to have "recvonly" direction'); + }); + }, `createOffer() with offerToReceive${capsKind} should create a "recvonly" transceiver`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer(offerToReceiveTrue) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'recvonly', + 'Expect transceiver to have "recvonly" direction'); + }) + .then(() => pc.createOffer(offerToReceiveTrue)) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to still have only one transceiver'); + }) + ; + }, `offerToReceive${capsKind} option should be ignored if a non-stopped "recvonly" transceiver exists`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return getTrackFromUserMedia(kind) + .then(([track, stream]) => { + pc.addTrack(track, stream); + return pc.createOffer(); + }) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'sendrecv', + 'Expect transceiver to have "sendrecv" direction'); + }) + .then(() => pc.createOffer(offerToReceiveTrue)) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to still have only one transceiver'); + }) + ; + }, `offerToReceive${capsKind} option should be ignored if a non-stopped "sendrecv" transceiver exists`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return getTrackFromUserMedia(kind) + .then(([track, stream]) => { + pc.addTrack(track, stream); + return pc.createOffer(offerToReceiveFalse); + }) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'sendonly', + 'Expect transceiver to have "sendonly" direction'); + }) + ; + }, `offerToReceive${capsKind} set to false with a track should create a "sendonly" transceiver`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + pc.addTransceiver(kind, {direction: 'recvonly'}); + + return pc.createOffer(offerToReceiveFalse) + .then(() => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'inactive', + 'Expect transceiver to have "inactive" direction'); + }) + ; + }, `offerToReceive${capsKind} set to false with a "recvonly" transceiver should change the direction to "inactive"`); + + promise_test(t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const pc2 = new RTCPeerConnection(); + + t.add_cleanup(() => pc2.close()); + + return getTrackFromUserMedia(kind) + .then(([track, stream]) => { + pc.addTrack(track, stream); + return pc.createOffer(); + }) + .then((offer) => pc.setLocalDescription(offer)) + .then(() => pc2.setRemoteDescription(pc.localDescription)) + .then(() => pc2.createAnswer()) + .then((answer) => pc2.setLocalDescription(answer)) + .then(() => pc.setRemoteDescription(pc2.localDescription)) + .then(() => pc.createOffer(offerToReceiveFalse)) + .then((offer) => { + assert_equals(pc.getTransceivers().length, 1, + 'Expect pc to have one transceiver'); + + const transceiver = pc.getTransceivers()[0]; + assert_equals(transceiver.direction, 'sendonly', + 'Expect transceiver to have "sendonly" direction'); + }) + ; + }, `subsequent offerToReceive${capsKind} set to false with a track should change the direction to "sendonly"`); + }); + + promise_test(t => { + const pc = new RTCPeerConnection(); + + t.add_cleanup(() => pc.close()); + + return pc.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true }) + .then(() => { + assert_equals(pc.getTransceivers().length, 2, + 'Expect pc to have two transceivers'); + + assert_equals(pc.getTransceivers()[0].direction, 'recvonly', + 'Expect first transceiver to have "recvonly" direction'); + assert_equals(pc.getTransceivers()[1].direction, 'recvonly', + 'Expect second transceiver to have "recvonly" direction'); + }); + }, 'offerToReceiveAudio and Video should create two "recvonly" transceivers'); + +</script> diff --git a/testing/web-platform/tests/webrtc/legacy/RTCRtpTransceiver-with-OfferToReceive-options.https.html b/testing/web-platform/tests/webrtc/legacy/RTCRtpTransceiver-with-OfferToReceive-options.https.html new file mode 100644 index 0000000000..65a4d7e393 --- /dev/null +++ b/testing/web-platform/tests/webrtc/legacy/RTCRtpTransceiver-with-OfferToReceive-options.https.html @@ -0,0 +1,172 @@ +<!doctype html> +<meta charset=utf-8> +<title>RTCRtpTransceiver with OfferToReceive legacy options</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src='/mediacapture-streams/permission-helper.js'></script> +<script src="../RTCPeerConnection-helper.js"></script> +<script> + 'use strict'; + + const stopTracks = (...streams) => { + streams.forEach(stream => stream.getTracks().forEach(track => track.stop())); + }; + + // comparable() - produces copy of object that is JSON comparable. + // o = original object (required) + // t = template of what to examine. Useful if o is non-enumerable (optional) + + const comparable = (o, t = o) => { + if (typeof o != 'object' || !o) { + return o; + } + if (Array.isArray(t) && Array.isArray(o)) { + return o.map((n, i) => comparable(n, t[i])); + } + return Object.keys(t).sort() + .reduce((r, key) => (r[key] = comparable(o[key], t[key]), r), {}); + }; + + const stripKeyQuotes = s => s.replace(/"(\w+)":/g, "$1:"); + + const hasProps = (observed, expected) => { + const observable = comparable(observed, expected); + assert_equals(stripKeyQuotes(JSON.stringify(observable)), + stripKeyQuotes(JSON.stringify(comparable(expected)))); + }; + + const checkAddTransceiverWithStream = async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + await setMediaPermission(); + const audioStream = await navigator.mediaDevices.getUserMedia({audio: true}); + const videoStream = await navigator.mediaDevices.getUserMedia({video: true}); + t.add_cleanup(() => stopTracks(audioStream, videoStream)); + + const audio = audioStream.getAudioTracks()[0]; + const video = videoStream.getVideoTracks()[0]; + + pc.addTransceiver(audio, {streams: [audioStream]}); + pc.addTransceiver(video, {streams: [videoStream]}); + + hasProps(pc.getTransceivers(), + [ + { + receiver: {track: {kind: "audio"}}, + sender: {track: audio}, + direction: "sendrecv", + mid: null, + currentDirection: null, + stopped: false + }, + { + receiver: {track: {kind: "video"}}, + sender: {track: video}, + direction: "sendrecv", + mid: null, + currentDirection: null, + stopped: false + } + ]); + + const offer = await pc.createOffer(); + assert_true(offer.sdp.includes("a=msid:" + audioStream.id), + "offer contains the expected audio msid"); + assert_true(offer.sdp.includes("a=msid:" + videoStream.id), + "offer contains the expected video msid"); + }; + + const checkAddTransceiverWithOfferToReceive = async (t, kinds) => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + + const propsToSet = kinds.map(kind => { + if (kind == "audio") { + return "offerToReceiveAudio"; + } else if (kind == "video") { + return "offerToReceiveVideo"; + } + }); + + const options = {}; + + for (const prop of propsToSet) { + options[prop] = true; + } + + let offer = await pc.createOffer(options); + + const expected = []; + + if (options.offerToReceiveAudio) { + expected.push( + { + receiver: {track: {kind: "audio"}}, + sender: {track: null}, + direction: "recvonly", + mid: null, + currentDirection: null, + stopped: false + }); + } + + if (options.offerToReceiveVideo) { + expected.push( + { + receiver: {track: {kind: "video"}}, + sender: {track: null}, + direction: "recvonly", + mid: null, + currentDirection: null, + stopped: false + }); + } + + hasProps(pc.getTransceivers(), expected); + + // Test offerToReceive: false + for (const prop of propsToSet) { + options[prop] = false; + } + + // Check that sendrecv goes to sendonly + for (const transceiver of pc.getTransceivers()) { + transceiver.direction = "sendrecv"; + } + + for (const transceiverCheck of expected) { + transceiverCheck.direction = "sendonly"; + } + + offer = await pc.createOffer(options); + hasProps(pc.getTransceivers(), expected); + + // Check that recvonly goes to inactive + for (const transceiver of pc.getTransceivers()) { + transceiver.direction = "recvonly"; + } + + for (const transceiverCheck of expected) { + transceiverCheck.direction = "inactive"; + } + + offer = await pc.createOffer(options); + hasProps(pc.getTransceivers(), expected); + }; + +const tests = [ + checkAddTransceiverWithStream, + function checkAddTransceiverWithOfferToReceiveAudio(t) { + return checkAddTransceiverWithOfferToReceive(t, ["audio"]); + }, + function checkAddTransceiverWithOfferToReceiveVideo(t) { + return checkAddTransceiverWithOfferToReceive(t, ["video"]); + }, + function checkAddTransceiverWithOfferToReceiveBoth(t) { + return checkAddTransceiverWithOfferToReceive(t, ["audio", "video"]); + } +].forEach(test => promise_test(test, test.name)); + +</script> diff --git a/testing/web-platform/tests/webrtc/legacy/onaddstream.https.html b/testing/web-platform/tests/webrtc/legacy/onaddstream.https.html new file mode 100644 index 0000000000..b5e8a402b8 --- /dev/null +++ b/testing/web-platform/tests/webrtc/legacy/onaddstream.https.html @@ -0,0 +1,157 @@ +<!doctype html> +<meta charset=utf-8> +<title>onaddstream tests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src='/mediacapture-streams/permission-helper.js'></script> +<script> + 'use strict'; + + const stopTracks = (...streams) => { + streams.forEach(stream => stream.getTracks().forEach(track => track.stop())); + }; + + const collectEvents = (target, name, check) => { + const events = []; + const handler = e => { + check(e); + events.push(e); + }; + + target.addEventListener(name, handler); + + const finishCollecting = () => { + target.removeEventListener(name, handler); + return events; + }; + + return {finish: finishCollecting}; + }; + + const collectAddTrackEvents = stream => { + const checkEvent = e => { + assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); + assert_true(stream.getTracks().includes(e.track), + "track in addtrack event is in the stream"); + }; + return collectEvents(stream, "addtrack", checkEvent); + }; + + const collectRemoveTrackEvents = stream => { + const checkEvent = e => { + assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); + assert_true(!stream.getTracks().includes(e.track), + "track in removetrack event is not in the stream"); + }; + return collectEvents(stream, "removetrack", checkEvent); + }; + + const collectTrackEvents = pc => { + const checkEvent = e => { + assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); + assert_true(e.receiver instanceof RTCRtpReceiver, "Receiver is set on event"); + assert_true(e.transceiver instanceof RTCRtpTransceiver, "Transceiver is set on event"); + assert_true(Array.isArray(e.streams), "Streams is set on event"); + e.streams.forEach(stream => { + assert_true(stream.getTracks().includes(e.track), + "Each stream in event contains the track"); + }); + assert_equals(e.receiver, e.transceiver.receiver, + "Receiver belongs to transceiver"); + assert_equals(e.track, e.receiver.track, + "Track belongs to receiver"); + }; + + return collectEvents(pc, "track", checkEvent); + }; + + // comparable() - produces copy of object that is JSON comparable. + // o = original object (required) + // t = template of what to examine. Useful if o is non-enumerable (optional) + + const comparable = (o, t = o) => { + if (typeof o != 'object' || !o) { + return o; + } + if (Array.isArray(t) && Array.isArray(o)) { + return o.map((n, i) => comparable(n, t[i])); + } + return Object.keys(t).sort() + .reduce((r, key) => (r[key] = comparable(o[key], t[key]), r), {}); + }; + + const stripKeyQuotes = s => s.replace(/"(\w+)":/g, "$1:"); + + const hasProps = (observed, expected) => { + const observable = comparable(observed, expected); + assert_equals(stripKeyQuotes(JSON.stringify(observable)), + stripKeyQuotes(JSON.stringify(comparable(expected)))); + }; + + promise_test(async t => { + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + await setMediaPermission(); + const stream1 = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); + t.add_cleanup(() => stopTracks(stream1)); + const audio1 = stream1.getAudioTracks()[0]; + pc1.addTrack(audio1, stream1); + const video1 = stream1.getVideoTracks()[0]; + pc1.addTrack(video1, stream1); + + const pc2 = new RTCPeerConnection(); + t.add_cleanup(() => pc2.close()); + const stream2 = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); + t.add_cleanup(() => stopTracks(stream2)); + const audio2 = stream2.getAudioTracks()[0]; + pc2.addTrack(audio2, stream2); + const video2 = stream2.getVideoTracks()[0]; + pc2.addTrack(video2, stream2); + + const offer = await pc1.createOffer(); + + let trackEventCollector = collectTrackEvents(pc2); + let addstreamEventCollector = collectEvents(pc2, "addstream", e => { + hasProps(e, {stream: {id: stream1.id}}); + assert_equals(e.stream.getAudioTracks().length, 1, "One audio track"); + assert_equals(e.stream.getVideoTracks().length, 1, "One video track"); + }); + + await pc2.setRemoteDescription(offer); + + let addstreamEvents = addstreamEventCollector.finish(); + assert_equals(addstreamEvents.length, 1, "Should have 1 addstream event"); + + let trackEvents = trackEventCollector.finish(); + + hasProps(trackEvents, + [ + {streams: [addstreamEvents[0].stream]}, + {streams: [addstreamEvents[0].stream]} + ]); + + await pc1.setLocalDescription(offer); + const answer = await pc2.createAnswer(); + + trackEventCollector = collectTrackEvents(pc1); + addstreamEventCollector = collectEvents(pc1, "addstream", e => { + hasProps(e, {stream: {id: stream2.id}}); + assert_equals(e.stream.getAudioTracks().length, 1, "One audio track"); + assert_equals(e.stream.getVideoTracks().length, 1, "One video track"); + }); + + await pc1.setRemoteDescription(answer); + addstreamEvents = addstreamEventCollector.finish(); + assert_equals(addstreamEvents.length, 1, "Should have 1 addstream event"); + + trackEvents = trackEventCollector.finish(); + + hasProps(trackEvents, + [ + {streams: [addstreamEvents[0].stream]}, + {streams: [addstreamEvents[0].stream]} + ]); + },"Check onaddstream"); +</script> |