| <!doctype html> |
| <meta charset=utf-8> |
| <title>RTCRtpParameters transactionId</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="dictionary-helper.js"></script> |
| <script src="RTCRtpParameters-helper.js"></script> |
| <script> |
| 'use strict'; |
| |
| // Test is based on the following editor draft: |
| // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html |
| |
| /* |
| 5.1. RTCPeerConnection Interface Extensions |
| partial interface RTCPeerConnection { |
| RTCRtpTransceiver addTransceiver((MediaStreamTrack or DOMString) trackOrKind, |
| optional RTCRtpTransceiverInit init); |
| ... |
| }; |
| |
| dictionary RTCRtpTransceiverInit { |
| RTCRtpTransceiverDirection direction = "sendrecv"; |
| sequence<MediaStream> streams; |
| sequence<RTCRtpEncodingParameters> sendEncodings; |
| }; |
| |
| addTransceiver |
| 2. If the dictionary argument is present, and it has a sendEncodings member, |
| let sendEncodings be that list of RTCRtpEncodingParameters objects, or an |
| empty list otherwise. |
| 7. Create an RTCRtpSender with track, streams and sendEncodings and let |
| sender be the result. |
| |
| 5.2. RTCRtpSender Interface |
| interface RTCRtpSender { |
| Promise<void> setParameters(optional RTCRtpParameters parameters); |
| RTCRtpParameters getParameters(); |
| }; |
| |
| dictionary RTCRtpParameters { |
| DOMString transactionId; |
| sequence<RTCRtpEncodingParameters> encodings; |
| sequence<RTCRtpHeaderExtensionParameters> headerExtensions; |
| RTCRtcpParameters rtcp; |
| sequence<RTCRtpCodecParameters> codecs; |
| }; |
| |
| getParameters |
| - transactionId is set to a new unique identifier, used to match this |
| getParameters call to a setParameters call that may occur later. |
| */ |
| |
| /* |
| 5.2. getParameters |
| - transactionId is set to a new unique identifier, used to match this |
| getParameters call to a setParameters call that may occur later. |
| */ |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param1 = sender.getParameters(); |
| const param2 = sender.getParameters(); |
| assert_equals(typeof param1.transactionId, "string"); |
| assert_greater_than(param1.transactionId.length, 0); |
| assert_equals(typeof param2.transactionId, "string"); |
| assert_greater_than(param2.transactionId.length, 0); |
| // Don't assert_equals() because the transcation ID is different on each run |
| // which makes the -expected.txt baseline different each failed run. |
| assert_true(param1.transactionId == param2.transactionId); |
| |
| await undefined; |
| const param3 = sender.getParameters(); |
| assert_equals(typeof param3.transactionId, "string"); |
| assert_greater_than(param3.transactionId.length, 0); |
| assert_equals(param1.transactionId, param3.transactionId); |
| }, `sender.getParameters() should return the same transaction ID if called back-to-back without relinquishing the event loop, even if the microtask queue runs`); |
| |
| test(t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param1 = sender.getParameters(); |
| sender.setParameters(param1); |
| const param2 = sender.getParameters(); |
| assert_equals(typeof param1.transactionId, "string"); |
| assert_greater_than(param1.transactionId.length, 0); |
| assert_equals(typeof param2.transactionId, "string"); |
| assert_greater_than(param2.transactionId.length, 0); |
| |
| // Don't assert_equals() because the transcation ID is different on each run |
| // which makes the -expected.txt baseline different each failed run. |
| assert_true(param1.transactionId == param2.transactionId); |
| }, `sender.getParameters() should return the same transaction ID if called back-to-back without relinquishing the event loop, even if there is an intervening call to setParameters`); |
| |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param1 = sender.getParameters(); |
| await pc.createOffer(); |
| const param2 = sender.getParameters(); |
| assert_equals(typeof param1.transactionId, "string"); |
| assert_greater_than(param1.transactionId.length, 0); |
| assert_equals(typeof param2.transactionId, "string"); |
| assert_greater_than(param2.transactionId.length, 0); |
| |
| assert_not_equals(param1.transactionId, param2.transactionId); |
| }, `sender.getParameters() should return a different transaction ID if the event loop is relinquished between multiple calls`); |
| |
| /* |
| 5.2. setParameters |
| 7. If parameters.encodings.length is different from N, or if any parameter |
| in the parameters argument, marked as a Read-only parameter, has a value |
| that is different from the corresponding parameter value returned from |
| sender.getParameters(), abort these steps and return a promise rejected |
| with a newly created InvalidModificationError. Note that this also applies |
| to transactionId. |
| */ |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param = sender.getParameters(); |
| |
| const { transactionId } = param; |
| param.transactionId = `${transactionId}-modified`; |
| |
| await promise_rejects_dom(t, 'InvalidModificationError', |
| sender.setParameters(param)); |
| }, `sender.setParameters() with transaction ID different from last getParameters() should reject with InvalidModificationError`); |
| |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param = sender.getParameters(); |
| |
| delete param.transactionId; |
| |
| await promise_rejects_js(t, TypeError, |
| sender.setParameters(param)); |
| }, `sender.setParameters() with transaction ID unset should reject with TypeError`); |
| |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param = sender.getParameters(); |
| |
| await sender.setParameters(param); |
| await promise_rejects_dom(t, 'InvalidStateError', sender.setParameters(param)) |
| }, `setParameters() twice with the same parameters should reject with InvalidStateError`); |
| |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param1 = sender.getParameters(); |
| // Queue a task, does not really matter what kind |
| await pc.createOffer(); |
| const param2 = sender.getParameters(); |
| |
| assert_not_equals(param1.transactionId, param2.transactionId); |
| |
| await promise_rejects_dom(t, 'InvalidModificationError', |
| sender.setParameters(param1)); |
| }, `setParameters() with parameters older than last getParameters() should reject with InvalidModificationError`); |
| |
| promise_test(async t => { |
| const pc = new RTCPeerConnection(); |
| t.add_cleanup(() => pc.close()); |
| const { sender } = pc.addTransceiver('audio'); |
| |
| const param1 = sender.getParameters(); |
| await pc.createOffer(); |
| |
| await promise_rejects_dom(t, 'InvalidStateError', |
| sender.setParameters(param1)); |
| }, `setParameters() when the event loop has been relinquished since the last getParameters() should reject with InvalidStateError`); |
| |
| </script> |