From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- testing/web-platform/tests/webrtc/META.yml | 9 + testing/web-platform/tests/webrtc/README.md | 12 + .../tests/webrtc/RTCCertificate-postMessage.html | 78 + .../web-platform/tests/webrtc/RTCCertificate.html | 283 +++ .../webrtc/RTCConfiguration-bundlePolicy.html | 128 ++ .../tests/webrtc/RTCConfiguration-helper.js | 24 + .../RTCConfiguration-iceCandidatePoolSize.html | 117 + .../tests/webrtc/RTCConfiguration-iceServers.html | 330 +++ .../RTCConfiguration-iceTransportPolicy.html | 306 +++ .../webrtc/RTCConfiguration-rtcpMuxPolicy.html | 196 ++ .../tests/webrtc/RTCDTMFSender-helper.js | 149 ++ .../webrtc/RTCDTMFSender-insertDTMF.https.html | 176 ++ .../RTCDTMFSender-ontonechange-long.https.html | 50 + .../webrtc/RTCDTMFSender-ontonechange.https.html | 294 +++ .../webrtc/RTCDataChannel-binaryType.window.js | 27 + .../webrtc/RTCDataChannel-bufferedAmount.html | 287 +++ .../tests/webrtc/RTCDataChannel-close.html | 180 ++ .../tests/webrtc/RTCDataChannel-iceRestart.html | 76 + .../tests/webrtc/RTCDataChannel-id.html | 345 +++ .../webrtc/RTCDataChannel-send-blob-order.html | 31 + .../tests/webrtc/RTCDataChannel-send.html | 336 +++ .../webrtc/RTCDataChannelEvent-constructor.html | 41 + .../RTCDtlsTransport-getRemoteCertificates.html | 97 + .../tests/webrtc/RTCDtlsTransport-state.html | 142 ++ testing/web-platform/tests/webrtc/RTCError.html | 89 + .../tests/webrtc/RTCIceCandidate-constructor.html | 234 ++ ...RTCIceConnectionState-candidate-pair.https.html | 33 + .../web-platform/tests/webrtc/RTCIceTransport.html | 193 ++ .../tests/webrtc/RTCPeerConnection-GC.https.html | 92 + .../RTCPeerConnection-SLD-SRD-timing.https.html | 24 + ...PeerConnection-add-track-no-deadlock.https.html | 31 + ...Connection-addIceCandidate-connectionSetup.html | 92 + ...eerConnection-addIceCandidate-timing.https.html | 149 ++ .../webrtc/RTCPeerConnection-addIceCandidate.html | 631 ++++++ .../webrtc/RTCPeerConnection-addTrack.https.html | 394 ++++ .../RTCPeerConnection-addTransceiver.https.html | 441 ++++ .../RTCPeerConnection-canTrickleIceCandidates.html | 62 + .../RTCPeerConnection-candidate-in-sdp.https.html | 26 + .../RTCPeerConnection-capture-video.https.html | 72 + .../RTCPeerConnection-connectionState.https.html | 291 +++ .../webrtc/RTCPeerConnection-constructor.html | 76 + .../webrtc/RTCPeerConnection-createAnswer.html | 41 + .../RTCPeerConnection-createDataChannel.html | 758 +++++++ .../webrtc/RTCPeerConnection-createOffer.html | 134 ++ ...ection-description-attributes-timing.https.html | 81 + ...ection-explicit-rollback-iceGatheringState.html | 53 + .../RTCPeerConnection-generateCertificate.html | 138 ++ .../webrtc/RTCPeerConnection-getStats.https.html | 422 ++++ .../webrtc/RTCPeerConnection-getTransceivers.html | 39 + .../webrtc/RTCPeerConnection-helper-test.html | 21 + .../tests/webrtc/RTCPeerConnection-helper.js | 722 ++++++ ...tion-iceConnectionState-disconnected.https.html | 30 + ...RTCPeerConnection-iceConnectionState.https.html | 396 ++++ .../RTCPeerConnection-iceGatheringState.html | 244 +++ ...RTCPeerConnection-mandatory-getStats.https.html | 277 +++ .../webrtc/RTCPeerConnection-ondatachannel.html | 374 ++++ ...TCPeerConnection-onicecandidateerror.https.html | 38 + .../RTCPeerConnection-onnegotiationneeded.html | 627 ++++++ ...erConnection-onsignalingstatechanged.https.html | 71 + .../webrtc/RTCPeerConnection-ontrack.https.html | 258 +++ .../webrtc/RTCPeerConnection-operations.https.html | 425 ++++ ...RTCPeerConnection-perfect-negotiation-helper.js | 153 ++ ...fect-negotiation-stress-glare-linear.https.html | 23 + ...ion-perfect-negotiation-stress-glare.https.html | 23 + ...TCPeerConnection-perfect-negotiation.https.html | 22 + .../RTCPeerConnection-plan-b-is-not-supported.html | 28 + .../RTCPeerConnection-relay-canvas.https.html | 84 + .../RTCPeerConnection-remote-track-mute.https.html | 132 ++ .../RTCPeerConnection-removeTrack.https.html | 338 +++ ...ction-restartIce-onnegotiationneeded.https.html | 29 + .../webrtc/RTCPeerConnection-restartIce.https.html | 482 ++++ ...CPeerConnection-setDescription-transceiver.html | 295 +++ ...CPeerConnection-setLocalDescription-answer.html | 230 ++ ...TCPeerConnection-setLocalDescription-offer.html | 229 ++ ...on-setLocalDescription-parameterless.https.html | 170 ++ ...eerConnection-setLocalDescription-pranswer.html | 166 ++ ...eerConnection-setLocalDescription-rollback.html | 167 ++ .../RTCPeerConnection-setLocalDescription.html | 152 ++ ...PeerConnection-setRemoteDescription-answer.html | 123 ++ ...PeerConnection-setRemoteDescription-nomsid.html | 40 + ...CPeerConnection-setRemoteDescription-offer.html | 356 +++ ...erConnection-setRemoteDescription-pranswer.html | 166 ++ ...on-setRemoteDescription-replaceTrack.https.html | 115 + ...erConnection-setRemoteDescription-rollback.html | 602 +++++ ...ction-setRemoteDescription-simulcast.https.html | 50 + ...nnection-setRemoteDescription-tracks.https.html | 385 ++++ .../RTCPeerConnection-setRemoteDescription.html | 171 ++ .../RTCPeerConnection-transceivers.https.html | 509 +++++ .../RTCPeerConnection-transport-stats.https.html | 46 + .../RTCPeerConnection-videoDetectorTest.html | 84 + .../webrtc/RTCPeerConnectionIceErrorEvent.html | 26 + .../RTCPeerConnectionIceEvent-constructor.html | 126 ++ .../tests/webrtc/RTCRtpCapabilities-helper.js | 52 + .../tests/webrtc/RTCRtpParameters-codecs.html | 206 ++ .../tests/webrtc/RTCRtpParameters-encodings.html | 543 +++++ .../webrtc/RTCRtpParameters-headerExtensions.html | 74 + .../tests/webrtc/RTCRtpParameters-helper.js | 259 +++ .../tests/webrtc/RTCRtpParameters-rtcp.html | 104 + .../webrtc/RTCRtpParameters-transactionId.html | 190 ++ .../webrtc/RTCRtpReceiver-getCapabilities.html | 39 + ...TCRtpReceiver-getContributingSources.https.html | 35 + .../tests/webrtc/RTCRtpReceiver-getParameters.html | 73 + .../webrtc/RTCRtpReceiver-getStats.https.html | 145 ++ ...tpReceiver-getSynchronizationSources.https.html | 105 + ...RTCRtpSender-encode-same-track-twice.https.html | 66 + .../tests/webrtc/RTCRtpSender-getCapabilities.html | 45 + .../tests/webrtc/RTCRtpSender-getStats.https.html | 97 + .../webrtc/RTCRtpSender-replaceTrack.https.html | 338 +++ .../tests/webrtc/RTCRtpSender-setParameters.html | 52 + .../webrtc/RTCRtpSender-setStreams.https.html | 127 ++ .../tests/webrtc/RTCRtpSender-transport.https.html | 152 ++ .../tests/webrtc/RTCRtpSender.https.html | 20 + .../tests/webrtc/RTCRtpTransceiver-direction.html | 94 + .../RTCRtpTransceiver-setCodecPreferences.html | 322 +++ .../tests/webrtc/RTCRtpTransceiver-stop.html | 155 ++ .../webrtc/RTCRtpTransceiver-stopping.https.html | 217 ++ .../tests/webrtc/RTCRtpTransceiver.https.html | 2297 ++++++++++++++++++++ .../tests/webrtc/RTCSctpTransport-constructor.html | 125 ++ .../tests/webrtc/RTCSctpTransport-events.html | 55 + .../tests/webrtc/RTCSctpTransport-maxChannels.html | 49 + .../webrtc/RTCSctpTransport-maxMessageSize.html | 206 ++ .../web-platform/tests/webrtc/RTCStats-helper.js | 973 +++++++++ .../tests/webrtc/RTCTrackEvent-constructor.html | 159 ++ .../tests/webrtc/RTCTrackEvent-fire.html | 168 ++ .../tests/webrtc/RollbackEvents.https.html | 231 ++ .../tests/webrtc/coverage/RTCDTMFSender.txt | 122 ++ .../tests/webrtc/coverage/identity.txt | 220 ++ .../webrtc/coverage/set-session-description.txt | 240 ++ .../web-platform/tests/webrtc/dictionary-helper.js | 101 + testing/web-platform/tests/webrtc/getstats.html | 130 ++ testing/web-platform/tests/webrtc/historical.html | 51 + .../tests/webrtc/idlharness.https.window.js | 146 ++ .../web-platform/tests/webrtc/legacy/README.txt | 2 + ...CPeerConnection-createOffer-offerToReceive.html | 274 +++ ...nsceiver-with-OfferToReceive-options.https.html | 172 ++ .../tests/webrtc/legacy/onaddstream.https.html | 157 ++ .../web-platform/tests/webrtc/no-media-call.html | 100 + .../web-platform/tests/webrtc/promises-call.html | 113 + .../web-platform/tests/webrtc/protocol/README.txt | 22 + .../protocol/RTCPeerConnection-payloadTypes.html | 49 + .../tests/webrtc/protocol/bundle.https.html | 150 ++ .../webrtc/protocol/candidate-exchange.https.html | 218 ++ .../tests/webrtc/protocol/crypto-suite.https.html | 85 + .../tests/webrtc/protocol/dtls-certificates.html | 42 + .../protocol/dtls-fingerprint-validation.html | 37 + .../tests/webrtc/protocol/dtls-setup.https.html | 135 ++ .../webrtc/protocol/h264-profile-levels.https.html | 115 + .../webrtc/protocol/handover-datachannel.html | 61 + .../tests/webrtc/protocol/handover.html | 72 + .../tests/webrtc/protocol/ice-state.https.html | 130 ++ .../tests/webrtc/protocol/ice-ufragpwd.html | 55 + .../webrtc/protocol/jsep-initial-offer.https.html | 41 + .../tests/webrtc/protocol/missing-fields.html | 47 + .../tests/webrtc/protocol/msid-generate.html | 160 ++ .../tests/webrtc/protocol/msid-parse.html | 83 + .../tests/webrtc/protocol/rtp-clockrate.html | 40 + .../tests/webrtc/protocol/rtp-demuxing.html | 109 + .../webrtc/protocol/rtp-extension-support.html | 78 + .../webrtc/protocol/rtp-headerextensions.html | 101 + .../tests/webrtc/protocol/rtp-payloadtypes.html | 61 + .../tests/webrtc/protocol/rtx-codecs.https.html | 153 ++ .../tests/webrtc/protocol/sctp-format.html | 25 + .../tests/webrtc/protocol/sdes-dont-dont-dont.html | 55 + .../tests/webrtc/protocol/simulcast-answer.html | 101 + .../tests/webrtc/protocol/simulcast-offer.html | 33 + .../tests/webrtc/protocol/split.https.html | 98 + .../tests/webrtc/protocol/unknown-mediatypes.html | 34 + .../tests/webrtc/protocol/video-codecs.https.html | 95 + .../tests/webrtc/protocol/vp8-fmtp.html | 44 + .../tests/webrtc/receiver-track-live.https.html | 72 + ...only-transceiver-can-become-sendrecv.https.html | 50 + .../RTCCertificate-postMessage-iframe.html | 9 + .../tests/webrtc/simplecall-no-ssrcs.https.html | 118 + .../tests/webrtc/simplecall.https.html | 109 + .../tests/webrtc/simulcast/basic.https.html | 23 + .../tests/webrtc/simulcast/getStats.https.html | 34 + .../tests/webrtc/simulcast/h264.https.html | 31 + .../simulcast/negotiation-encodings.https.html | 534 +++++ .../tests/webrtc/simulcast/rid-manipulation.html | 39 + .../simulcast/setParameters-active.https.html | 104 + .../simulcast/setParameters-encodings.https.html | 462 ++++ .../tests/webrtc/simulcast/simulcast.js | 254 +++ .../tests/webrtc/simulcast/vp8.https.html | 26 + .../simulcast/vp9-scalability-mode.https.html | 35 + .../tests/webrtc/simulcast/vp9.https.html | 26 + .../tests/webrtc/third_party/README.md | 5 + .../tests/webrtc/third_party/sdp/LICENSE | 19 + .../tests/webrtc/third_party/sdp/sdp.js | 825 +++++++ testing/web-platform/tests/webrtc/toJSON.html | 48 + .../web-platform/tests/webrtc/tools/.eslintrc.js | 154 ++ testing/web-platform/tests/webrtc/tools/README.md | 14 + .../webrtc/tools/codemod-peerconnection-addcleanup | 58 + .../tests/webrtc/tools/html-codemod.js | 34 + .../web-platform/tests/webrtc/tools/package.json | 16 + 194 files changed, 32544 insertions(+) create mode 100644 testing/web-platform/tests/webrtc/META.yml create mode 100644 testing/web-platform/tests/webrtc/README.md create mode 100644 testing/web-platform/tests/webrtc/RTCCertificate-postMessage.html create mode 100644 testing/web-platform/tests/webrtc/RTCCertificate.html create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-bundlePolicy.html create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-iceServers.html create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-iceTransportPolicy.html create mode 100644 testing/web-platform/tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html create mode 100644 testing/web-platform/tests/webrtc/RTCDTMFSender-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCDTMFSender-insertDTMF.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange-long.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-binaryType.window.js create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-bufferedAmount.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-close.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-iceRestart.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-id.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-send-blob-order.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannel-send.html create mode 100644 testing/web-platform/tests/webrtc/RTCDataChannelEvent-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html create mode 100644 testing/web-platform/tests/webrtc/RTCDtlsTransport-state.html create mode 100644 testing/web-platform/tests/webrtc/RTCError.html create mode 100644 testing/web-platform/tests/webrtc/RTCIceCandidate-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCIceConnectionState-candidate-pair.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCIceTransport.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-GC.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-SLD-SRD-timing.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-add-track-no-deadlock.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-timing.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-addTrack.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-addTransceiver.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-candidate-in-sdp.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-capture-video.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-connectionState.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-createAnswer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-createOffer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-description-attributes-timing.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-explicit-rollback-iceGatheringState.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-generateCertificate.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-getStats.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-getTransceivers.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-helper-test.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-ondatachannel.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-onicecandidateerror.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-onnegotiationneeded.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-ontrack.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-operations.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-plan-b-is-not-supported.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-relay-canvas.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-remote-track-mute.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-removeTrack.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setDescription-transceiver.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-answer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-offer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-pranswer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-answer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-simulcast.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-transceivers.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-transport-stats.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnection-videoDetectorTest.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnectionIceErrorEvent.html create mode 100644 testing/web-platform/tests/webrtc/RTCPeerConnectionIceEvent-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpCapabilities-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-codecs.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-encodings.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-headerExtensions.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-rtcp.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpParameters-transactionId.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpReceiver-getCapabilities.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpReceiver-getContributingSources.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpReceiver-getParameters.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpReceiver-getStats.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-encode-same-track-twice.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-getCapabilities.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-getStats.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-replaceTrack.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-setParameters.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-setStreams.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender-transport.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpSender.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpTransceiver-direction.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpTransceiver-stop.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpTransceiver-stopping.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCRtpTransceiver.https.html create mode 100644 testing/web-platform/tests/webrtc/RTCSctpTransport-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCSctpTransport-events.html create mode 100644 testing/web-platform/tests/webrtc/RTCSctpTransport-maxChannels.html create mode 100644 testing/web-platform/tests/webrtc/RTCSctpTransport-maxMessageSize.html create mode 100644 testing/web-platform/tests/webrtc/RTCStats-helper.js create mode 100644 testing/web-platform/tests/webrtc/RTCTrackEvent-constructor.html create mode 100644 testing/web-platform/tests/webrtc/RTCTrackEvent-fire.html create mode 100644 testing/web-platform/tests/webrtc/RollbackEvents.https.html create mode 100644 testing/web-platform/tests/webrtc/coverage/RTCDTMFSender.txt create mode 100644 testing/web-platform/tests/webrtc/coverage/identity.txt create mode 100644 testing/web-platform/tests/webrtc/coverage/set-session-description.txt create mode 100644 testing/web-platform/tests/webrtc/dictionary-helper.js create mode 100644 testing/web-platform/tests/webrtc/getstats.html create mode 100644 testing/web-platform/tests/webrtc/historical.html create mode 100644 testing/web-platform/tests/webrtc/idlharness.https.window.js create mode 100644 testing/web-platform/tests/webrtc/legacy/README.txt create mode 100644 testing/web-platform/tests/webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html create mode 100644 testing/web-platform/tests/webrtc/legacy/RTCRtpTransceiver-with-OfferToReceive-options.https.html create mode 100644 testing/web-platform/tests/webrtc/legacy/onaddstream.https.html create mode 100644 testing/web-platform/tests/webrtc/no-media-call.html create mode 100644 testing/web-platform/tests/webrtc/promises-call.html create mode 100644 testing/web-platform/tests/webrtc/protocol/README.txt create mode 100644 testing/web-platform/tests/webrtc/protocol/RTCPeerConnection-payloadTypes.html create mode 100644 testing/web-platform/tests/webrtc/protocol/bundle.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/candidate-exchange.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/crypto-suite.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/dtls-certificates.html create mode 100644 testing/web-platform/tests/webrtc/protocol/dtls-fingerprint-validation.html create mode 100644 testing/web-platform/tests/webrtc/protocol/dtls-setup.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/h264-profile-levels.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/handover-datachannel.html create mode 100644 testing/web-platform/tests/webrtc/protocol/handover.html create mode 100644 testing/web-platform/tests/webrtc/protocol/ice-state.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/ice-ufragpwd.html create mode 100644 testing/web-platform/tests/webrtc/protocol/jsep-initial-offer.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/missing-fields.html create mode 100644 testing/web-platform/tests/webrtc/protocol/msid-generate.html create mode 100644 testing/web-platform/tests/webrtc/protocol/msid-parse.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtp-clockrate.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtp-demuxing.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtp-extension-support.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtp-headerextensions.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtp-payloadtypes.html create mode 100644 testing/web-platform/tests/webrtc/protocol/rtx-codecs.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/sctp-format.html create mode 100644 testing/web-platform/tests/webrtc/protocol/sdes-dont-dont-dont.html create mode 100644 testing/web-platform/tests/webrtc/protocol/simulcast-answer.html create mode 100644 testing/web-platform/tests/webrtc/protocol/simulcast-offer.html create mode 100644 testing/web-platform/tests/webrtc/protocol/split.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/unknown-mediatypes.html create mode 100644 testing/web-platform/tests/webrtc/protocol/video-codecs.https.html create mode 100644 testing/web-platform/tests/webrtc/protocol/vp8-fmtp.html create mode 100644 testing/web-platform/tests/webrtc/receiver-track-live.https.html create mode 100644 testing/web-platform/tests/webrtc/recvonly-transceiver-can-become-sendrecv.https.html create mode 100644 testing/web-platform/tests/webrtc/resources/RTCCertificate-postMessage-iframe.html create mode 100644 testing/web-platform/tests/webrtc/simplecall-no-ssrcs.https.html create mode 100644 testing/web-platform/tests/webrtc/simplecall.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/basic.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/getStats.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/h264.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/negotiation-encodings.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/rid-manipulation.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/setParameters-active.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/setParameters-encodings.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/simulcast.js create mode 100644 testing/web-platform/tests/webrtc/simulcast/vp8.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/vp9-scalability-mode.https.html create mode 100644 testing/web-platform/tests/webrtc/simulcast/vp9.https.html create mode 100644 testing/web-platform/tests/webrtc/third_party/README.md create mode 100644 testing/web-platform/tests/webrtc/third_party/sdp/LICENSE create mode 100644 testing/web-platform/tests/webrtc/third_party/sdp/sdp.js create mode 100644 testing/web-platform/tests/webrtc/toJSON.html create mode 100644 testing/web-platform/tests/webrtc/tools/.eslintrc.js create mode 100644 testing/web-platform/tests/webrtc/tools/README.md create mode 100644 testing/web-platform/tests/webrtc/tools/codemod-peerconnection-addcleanup create mode 100644 testing/web-platform/tests/webrtc/tools/html-codemod.js create mode 100644 testing/web-platform/tests/webrtc/tools/package.json (limited to 'testing/web-platform/tests/webrtc') diff --git a/testing/web-platform/tests/webrtc/META.yml b/testing/web-platform/tests/webrtc/META.yml new file mode 100644 index 0000000000..69fcad76f1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/META.yml @@ -0,0 +1,9 @@ +spec: https://w3c.github.io/webrtc-pc/ +suggested_reviewers: + - snuggs + - alvestrand + - guidou + - henbos + - youennf + - rwaldron + - jan-ivar diff --git a/testing/web-platform/tests/webrtc/README.md b/testing/web-platform/tests/webrtc/README.md new file mode 100644 index 0000000000..4477e4f375 --- /dev/null +++ b/testing/web-platform/tests/webrtc/README.md @@ -0,0 +1,12 @@ +# WebRTC + +This directory contains the WebRTC test suite. + +## Acknowledgements + +Some data channel tests are based on the [data channel conformance test +suite][nplab-webrtc-dc-playground] of the Network Programming Lab of the Münster +University of Applied Sciences. We would like to thank Peter Titz, Felix Weinrank and Timo +Völker for agreeing to contribute their test cases to this repository. + +[nplab-webrtc-dc-playground]: https://github.com/nplab/WebRTC-Data-Channel-Playground/tree/master/conformance-tests diff --git a/testing/web-platform/tests/webrtc/RTCCertificate-postMessage.html b/testing/web-platform/tests/webrtc/RTCCertificate-postMessage.html new file mode 100644 index 0000000000..6cca240057 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCCertificate-postMessage.html @@ -0,0 +1,78 @@ + + +RTCCertificate persistent Tests + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCCertificate.html b/testing/web-platform/tests/webrtc/RTCCertificate.html new file mode 100644 index 0000000000..6b7626c92e --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCCertificate.html @@ -0,0 +1,283 @@ + + +RTCCertificate Tests + + + diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-bundlePolicy.html b/testing/web-platform/tests/webrtc/RTCConfiguration-bundlePolicy.html new file mode 100644 index 0000000000..e825d7b402 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-bundlePolicy.html @@ -0,0 +1,128 @@ + + +RTCConfiguration bundlePolicy + + + diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-helper.js b/testing/web-platform/tests/webrtc/RTCConfiguration-helper.js new file mode 100644 index 0000000000..fb8eb50995 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-helper.js @@ -0,0 +1,24 @@ +'use strict'; + +// Run a test function as two test cases. +// The first test case test the configuration by passing a given config +// to the constructor. +// The second test case create an RTCPeerConnection object with default +// configuration, then call setConfiguration with the provided config. +// The test function is given a constructor function to create +// a new instance of RTCPeerConnection with given config, +// either directly as constructor parameter or through setConfiguration. +function config_test(test_func, desc) { + test(() => { + test_func(config => new RTCPeerConnection(config)); + }, `new RTCPeerConnection(config) - ${desc}`); + + test(() => { + test_func(config => { + const pc = new RTCPeerConnection(); + assert_idl_attribute(pc, 'setConfiguration'); + pc.setConfiguration(config); + return pc; + }) + }, `setConfiguration(config) - ${desc}`); +} diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html b/testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html new file mode 100644 index 0000000000..495b043e12 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-iceCandidatePoolSize.html @@ -0,0 +1,117 @@ + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-iceServers.html b/testing/web-platform/tests/webrtc/RTCConfiguration-iceServers.html new file mode 100644 index 0000000000..1893ba02f3 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-iceServers.html @@ -0,0 +1,330 @@ + + +RTCConfiguration iceServers + + + + diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-iceTransportPolicy.html b/testing/web-platform/tests/webrtc/RTCConfiguration-iceTransportPolicy.html new file mode 100644 index 0000000000..ebc79048a3 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-iceTransportPolicy.html @@ -0,0 +1,306 @@ + + +RTCConfiguration iceTransportPolicy + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html b/testing/web-platform/tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html new file mode 100644 index 0000000000..48e772fb51 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html @@ -0,0 +1,196 @@ + +RTCConfiguration rtcpMuxPolicy + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDTMFSender-helper.js b/testing/web-platform/tests/webrtc/RTCDTMFSender-helper.js new file mode 100644 index 0000000000..4316c3804a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDTMFSender-helper.js @@ -0,0 +1,149 @@ +'use strict'; + +// Test is based on the following editor draft: +// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +// Code using this helper should also include RTCPeerConnection-helper.js +// in the main HTML file + +// The following helper functions are called from RTCPeerConnection-helper.js: +// getTrackFromUserMedia +// exchangeOfferAnswer + +// Create a RTCDTMFSender using getUserMedia() +// Connect the PeerConnection to another PC and wait until it is +// properly connected, so that DTMF can be sent. +function createDtmfSender(pc = new RTCPeerConnection()) { + let dtmfSender; + return getTrackFromUserMedia('audio') + .then(([track, mediaStream]) => { + const sender = pc.addTrack(track, mediaStream); + dtmfSender = sender.dtmf; + assert_true(dtmfSender instanceof RTCDTMFSender, + 'Expect audio sender.dtmf to be set to a RTCDTMFSender'); + // Note: spec bug open - https://github.com/w3c/webrtc-pc/issues/1774 + // on whether sending should be possible before negotiation. + const pc2 = new RTCPeerConnection(); + Object.defineProperty(pc, 'otherPc', { value: pc2 }); + exchangeIceCandidates(pc, pc2); + return exchangeOfferAnswer(pc, pc2); + }).then(() => { + if (!('canInsertDTMF' in dtmfSender)) { + return Promise.resolve(); + } + // Wait until dtmfSender.canInsertDTMF becomes true. + // Up to 150 ms has been observed in test. Wait 1 second + // in steps of 10 ms. + // Note: Using a short timeout and rejected promise in order to + // make test return a clear error message on failure. + return new Promise((resolve, reject) => { + let counter = 0; + step_timeout(function checkCanInsertDTMF() { + if (dtmfSender.canInsertDTMF) { + resolve(); + } else { + if (counter >= 100) { + reject('Waited too long for canInsertDTMF'); + return; + } + ++counter; + step_timeout(checkCanInsertDTMF, 10); + } + }, 0); + }); + }).then(() => { + return dtmfSender; + }); +} + +/* + Create an RTCDTMFSender and test tonechange events on it. + testFunc + Test function that is going to manipulate the DTMFSender. + It will be called with: + t - the test object + sender - the created RTCDTMFSender + pc - the associated RTCPeerConnection as second argument. + toneChanges + Array of expected tonechange events fired. The elements + are array of 3 items: + expectedTone + The expected character in event.tone + expectedToneBuffer + The expected new value of dtmfSender.toneBuffer + expectedDuration + The rough time since beginning or last tonechange event + was fired. + desc + Test description. + */ +function test_tone_change_events(testFunc, toneChanges, desc) { + // Convert to cumulative time + let cumulativeTime = 0; + const cumulativeToneChanges = toneChanges.map(c => { + cumulativeTime += c[2]; + return [c[0], c[1], cumulativeTime]; + }); + + // Wait for same duration as last expected duration + 100ms + // before passing test in case there are new tone events fired, + // in which case the test should fail. + const lastWait = toneChanges.pop()[2] + 100; + + promise_test(async t => { + const pc = new RTCPeerConnection(); + const dtmfSender = await createDtmfSender(pc); + const start = Date.now(); + + const allEventsReceived = new Promise(resolve => { + const onToneChange = t.step_func(ev => { + assert_true(ev instanceof RTCDTMFToneChangeEvent, + 'Expect tone change event object to be an RTCDTMFToneChangeEvent'); + + const { tone } = ev; + assert_equals(typeof tone, 'string', + 'Expect event.tone to be the tone string'); + + assert_greater_than(cumulativeToneChanges.length, 0, + 'More tonechange event is fired than expected'); + + const [ + expectedTone, expectedToneBuffer, expectedTime + ] = cumulativeToneChanges.shift(); + + assert_equals(tone, expectedTone, + `Expect current event.tone to be ${expectedTone}`); + + assert_equals(dtmfSender.toneBuffer, expectedToneBuffer, + `Expect dtmfSender.toneBuffer to be updated to ${expectedToneBuffer}`); + + // We check that the cumulative delay is at least the expected one, but + // system load may cause random delays, so we do not put any + // realistic upper bound on the timing of the events. + assert_between_inclusive(Date.now() - start, expectedTime, + expectedTime + 4000, + `Expect tonechange event for "${tone}" to be fired approximately after ${expectedTime} milliseconds`); + if (cumulativeToneChanges.length === 0) { + resolve(); + } + }); + + dtmfSender.addEventListener('tonechange', onToneChange); + }); + + testFunc(t, dtmfSender, pc); + await allEventsReceived; + const wait = ms => new Promise(resolve => t.step_timeout(resolve, ms)); + await wait(lastWait); + }, desc); +} + +// Get the one and only tranceiver from pc.getTransceivers(). +// Assumes that there is only one tranceiver in pc. +function getTransceiver(pc) { + const transceivers = pc.getTransceivers(); + assert_equals(transceivers.length, 1, + 'Expect there to be only one tranceiver in pc'); + + return transceivers[0]; +} diff --git a/testing/web-platform/tests/webrtc/RTCDTMFSender-insertDTMF.https.html b/testing/web-platform/tests/webrtc/RTCDTMFSender-insertDTMF.https.html new file mode 100644 index 0000000000..71cfe70171 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDTMFSender-insertDTMF.https.html @@ -0,0 +1,176 @@ + + +RTCDTMFSender.prototype.insertDTMF + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange-long.https.html b/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange-long.https.html new file mode 100644 index 0000000000..852194d024 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange-long.https.html @@ -0,0 +1,50 @@ + + + +RTCDTMFSender.prototype.ontonechange (Long Timeout) + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange.https.html b/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange.https.html new file mode 100644 index 0000000000..08dd6ada32 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDTMFSender-ontonechange.https.html @@ -0,0 +1,294 @@ + + +RTCDTMFSender.prototype.ontonechange + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-binaryType.window.js b/testing/web-platform/tests/webrtc/RTCDataChannel-binaryType.window.js new file mode 100644 index 0000000000..c63281bd51 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-binaryType.window.js @@ -0,0 +1,27 @@ +'use strict'; + +const validBinaryTypes = ['blob', 'arraybuffer']; +const invalidBinaryTypes = ['jellyfish', 'arraybuffer ', '', null, undefined]; + +for (const binaryType of validBinaryTypes) { + test((t) => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const dc = pc.createDataChannel('test-binary-type'); + + dc.binaryType = binaryType; + assert_equals(dc.binaryType, binaryType, `dc.binaryType should be '${binaryType}'`); + }, `Setting binaryType to '${binaryType}' should succeed`); +} + +for (const binaryType of invalidBinaryTypes) { + test((t) => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const dc = pc.createDataChannel('test-binary-type'); + + assert_throws_dom('SyntaxError', () => { + dc.binaryType = binaryType; + }); + }, `Setting invalid binaryType '${binaryType}' should throw SyntaxError`); +} diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-bufferedAmount.html b/testing/web-platform/tests/webrtc/RTCDataChannel-bufferedAmount.html new file mode 100644 index 0000000000..b1b793206c --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-bufferedAmount.html @@ -0,0 +1,287 @@ + + + +RTCDataChannel.prototype.bufferedAmount + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-close.html b/testing/web-platform/tests/webrtc/RTCDataChannel-close.html new file mode 100644 index 0000000000..64534fc507 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-close.html @@ -0,0 +1,180 @@ + + + +RTCDataChannel.prototype.close + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-iceRestart.html b/testing/web-platform/tests/webrtc/RTCDataChannel-iceRestart.html new file mode 100644 index 0000000000..1aec50a587 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-iceRestart.html @@ -0,0 +1,76 @@ + + + +RTCDataChannel interactions with ICE restart + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-id.html b/testing/web-platform/tests/webrtc/RTCDataChannel-id.html new file mode 100644 index 0000000000..10dc5eacb9 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-id.html @@ -0,0 +1,345 @@ + + +RTCDataChannel id attribute + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-send-blob-order.html b/testing/web-platform/tests/webrtc/RTCDataChannel-send-blob-order.html new file mode 100644 index 0000000000..3fcf116bc8 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-send-blob-order.html @@ -0,0 +1,31 @@ + + +RTCDataChannel.prototype.send for blobs + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-send.html b/testing/web-platform/tests/webrtc/RTCDataChannel-send.html new file mode 100644 index 0000000000..70cdf8657f --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannel-send.html @@ -0,0 +1,336 @@ + + + +RTCDataChannel.prototype.send + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDataChannelEvent-constructor.html b/testing/web-platform/tests/webrtc/RTCDataChannelEvent-constructor.html new file mode 100644 index 0000000000..265943ae56 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDataChannelEvent-constructor.html @@ -0,0 +1,41 @@ + + +RTCDataChannelEvent constructor + + + diff --git a/testing/web-platform/tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html b/testing/web-platform/tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html new file mode 100644 index 0000000000..899e603cbe --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html @@ -0,0 +1,97 @@ + + +RTCDtlsTransport.prototype.getRemoteCertificates + + + + diff --git a/testing/web-platform/tests/webrtc/RTCDtlsTransport-state.html b/testing/web-platform/tests/webrtc/RTCDtlsTransport-state.html new file mode 100644 index 0000000000..ca49fcc95f --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCDtlsTransport-state.html @@ -0,0 +1,142 @@ + + +RTCDtlsTransport + + + + diff --git a/testing/web-platform/tests/webrtc/RTCError.html b/testing/web-platform/tests/webrtc/RTCError.html new file mode 100644 index 0000000000..bcc5749bf7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCError.html @@ -0,0 +1,89 @@ + + +RTCError and RTCErrorInit + + + + diff --git a/testing/web-platform/tests/webrtc/RTCIceCandidate-constructor.html b/testing/web-platform/tests/webrtc/RTCIceCandidate-constructor.html new file mode 100644 index 0000000000..66d6962079 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCIceCandidate-constructor.html @@ -0,0 +1,234 @@ + +RTCIceCandidate constructor + + + diff --git a/testing/web-platform/tests/webrtc/RTCIceConnectionState-candidate-pair.https.html b/testing/web-platform/tests/webrtc/RTCIceConnectionState-candidate-pair.https.html new file mode 100644 index 0000000000..3b2c253401 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCIceConnectionState-candidate-pair.https.html @@ -0,0 +1,33 @@ + + + +RTCIceConnectionState and RTCIceCandidatePair + + + + diff --git a/testing/web-platform/tests/webrtc/RTCIceTransport.html b/testing/web-platform/tests/webrtc/RTCIceTransport.html new file mode 100644 index 0000000000..fe12c384e5 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCIceTransport.html @@ -0,0 +1,193 @@ + + +RTCIceTransport + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-GC.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-GC.https.html new file mode 100644 index 0000000000..76ae3087e4 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-GC.https.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-SLD-SRD-timing.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-SLD-SRD-timing.https.html new file mode 100644 index 0000000000..36bde06c96 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-SLD-SRD-timing.https.html @@ -0,0 +1,24 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-add-track-no-deadlock.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-add-track-no-deadlock.https.html new file mode 100644 index 0000000000..81e3b73643 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-add-track-no-deadlock.https.html @@ -0,0 +1,31 @@ + + +RTCPeerConnection addTrack does not deadlock + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html new file mode 100644 index 0000000000..cedc2ca8f0 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html @@ -0,0 +1,92 @@ + + +Test RTCPeerConnection.prototype.addIceCandidate + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-timing.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-timing.https.html new file mode 100644 index 0000000000..9793844f56 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate-timing.https.html @@ -0,0 +1,149 @@ + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html new file mode 100644 index 0000000000..d8e24d608b --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html @@ -0,0 +1,631 @@ + +Test RTCPeerConnection.prototype.addIceCandidate + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-addTrack.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-addTrack.https.html new file mode 100644 index 0000000000..91665822c4 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addTrack.https.html @@ -0,0 +1,394 @@ + + +RTCPeerConnection.prototype.addTrack + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-addTransceiver.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-addTransceiver.https.html new file mode 100644 index 0000000000..3fd83a76fe --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addTransceiver.https.html @@ -0,0 +1,441 @@ + + +RTCPeerConnection.prototype.addTransceiver + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html new file mode 100644 index 0000000000..09ad67751a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-canTrickleIceCandidates.html @@ -0,0 +1,62 @@ + + + + + RTCPeerConnection canTrickleIceCandidates tests + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-candidate-in-sdp.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-candidate-in-sdp.https.html new file mode 100644 index 0000000000..6c97afe94a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-candidate-in-sdp.https.html @@ -0,0 +1,26 @@ + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-capture-video.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-capture-video.https.html new file mode 100644 index 0000000000..b6c0222dc2 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-capture-video.https.html @@ -0,0 +1,72 @@ + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-connectionState.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-connectionState.https.html new file mode 100644 index 0000000000..d7716a1d4d --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-connectionState.https.html @@ -0,0 +1,291 @@ + + +RTCPeerConnection.prototype.connectionState + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html new file mode 100644 index 0000000000..1708b2705f --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-constructor.html @@ -0,0 +1,76 @@ + + +RTCPeerConnection constructor + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-createAnswer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-createAnswer.html new file mode 100644 index 0000000000..1970db0737 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-createAnswer.html @@ -0,0 +1,41 @@ + + +RTCPeerConnection.prototype.createAnswer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html new file mode 100644 index 0000000000..7ad8bf7d46 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html @@ -0,0 +1,758 @@ + + + +RTCPeerConnection.prototype.createDataChannel + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-createOffer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-createOffer.html new file mode 100644 index 0000000000..704fa3c646 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-createOffer.html @@ -0,0 +1,134 @@ + + +RTCPeerConnection.prototype.createOffer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-description-attributes-timing.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-description-attributes-timing.https.html new file mode 100644 index 0000000000..2d2565c3e1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-description-attributes-timing.https.html @@ -0,0 +1,81 @@ + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-explicit-rollback-iceGatheringState.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-explicit-rollback-iceGatheringState.html new file mode 100644 index 0000000000..e39b985bef --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-explicit-rollback-iceGatheringState.html @@ -0,0 +1,53 @@ + + +RTCPeerConnection.prototype.iceGatheringState + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-generateCertificate.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-generateCertificate.html new file mode 100644 index 0000000000..4cda97e9b7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-generateCertificate.html @@ -0,0 +1,138 @@ + + +Test RTCPeerConnection.generateCertificate + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-getStats.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-getStats.https.html new file mode 100644 index 0000000000..4889bcf4dd --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-getStats.https.html @@ -0,0 +1,422 @@ + + + +RTCPeerConnection.prototype.getStats + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-getTransceivers.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-getTransceivers.html new file mode 100644 index 0000000000..381b42b0cf --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-getTransceivers.html @@ -0,0 +1,39 @@ + + +RTCPeerConnection.prototype.getTransceivers + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-helper-test.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-helper-test.html new file mode 100644 index 0000000000..42f6652ac4 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-helper-test.html @@ -0,0 +1,21 @@ + + +RTCPeerConnection-helper tests + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-helper.js b/testing/web-platform/tests/webrtc/RTCPeerConnection-helper.js new file mode 100644 index 0000000000..eefe10579b --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-helper.js @@ -0,0 +1,722 @@ +'use strict' + +/* + * Helper Methods for testing the following methods in RTCPeerConnection: + * createOffer + * createAnswer + * setLocalDescription + * setRemoteDescription + * + * This file offers the following features: + * SDP similarity comparison + * Generating offer/answer using anonymous peer connection + * Test signalingstatechange event + * Test promise that never resolve + */ + +const audioLineRegex = /\r\nm=audio.+\r\n/g; +const videoLineRegex = /\r\nm=video.+\r\n/g; +const applicationLineRegex = /\r\nm=application.+\r\n/g; + +function countLine(sdp, regex) { + const matches = sdp.match(regex); + if(matches === null) { + return 0; + } else { + return matches.length; + } +} + +function countAudioLine(sdp) { + return countLine(sdp, audioLineRegex); +} + +function countVideoLine(sdp) { + return countLine(sdp, videoLineRegex); +} + +function countApplicationLine(sdp) { + return countLine(sdp, applicationLineRegex); +} + +function similarMediaDescriptions(sdp1, sdp2) { + if(sdp1 === sdp2) { + return true; + } else if( + countAudioLine(sdp1) !== countAudioLine(sdp2) || + countVideoLine(sdp1) !== countVideoLine(sdp2) || + countApplicationLine(sdp1) !== countApplicationLine(sdp2)) + { + return false; + } else { + return true; + } +} + +// Assert that given object is either an +// RTCSessionDescription or RTCSessionDescriptionInit +function assert_is_session_description(sessionDesc) { + if(sessionDesc instanceof RTCSessionDescription) { + return; + } + + assert_not_equals(sessionDesc, undefined, + 'Expect session description to be defined'); + + assert_true(typeof(sessionDesc) === 'object', + 'Expect sessionDescription to be either a RTCSessionDescription or an object'); + + assert_true(typeof(sessionDesc.type) === 'string', + 'Expect sessionDescription.type to be a string'); + + assert_true(typeof(sessionDesc.sdp) === 'string', + 'Expect sessionDescription.sdp to be a string'); +} + + +// We can't do string comparison to the SDP content, +// because RTCPeerConnection may return SDP that is +// slightly modified or reordered from what is given +// to it due to ICE candidate events or serialization. +// Instead, we create SDP with different number of media +// lines, and if the SDP strings are not the same, we +// simply count the media description lines and if they +// are the same, we assume it is the same. +function isSimilarSessionDescription(sessionDesc1, sessionDesc2) { + assert_is_session_description(sessionDesc1); + assert_is_session_description(sessionDesc2); + + if(sessionDesc1.type !== sessionDesc2.type) { + return false; + } else { + return similarMediaDescriptions(sessionDesc1.sdp, sessionDesc2.sdp); + } +} + +function assert_session_desc_similar(sessionDesc1, sessionDesc2) { + assert_true(isSimilarSessionDescription(sessionDesc1, sessionDesc2), + 'Expect both session descriptions to have the same count of media lines'); +} + +function assert_session_desc_not_similar(sessionDesc1, sessionDesc2) { + assert_false(isSimilarSessionDescription(sessionDesc1, sessionDesc2), + 'Expect both session descriptions to have different count of media lines'); +} + +async function generateDataChannelOffer(pc) { + pc.createDataChannel('test'); + const offer = await pc.createOffer(); + assert_equals(countApplicationLine(offer.sdp), 1, 'Expect m=application line to be present in generated SDP'); + return offer; +} + +async function generateAudioReceiveOnlyOffer(pc) +{ + try { + pc.addTransceiver('audio', { direction: 'recvonly' }); + return pc.createOffer(); + } catch(e) { + return pc.createOffer({ offerToReceiveAudio: true }); + } +} + +async function generateVideoReceiveOnlyOffer(pc) +{ + try { + pc.addTransceiver('video', { direction: 'recvonly' }); + return pc.createOffer(); + } catch(e) { + return pc.createOffer({ offerToReceiveVideo: true }); + } +} + +// Helper function to generate answer based on given offer using a freshly +// created RTCPeerConnection object +async function generateAnswer(offer) { + const pc = new RTCPeerConnection(); + await pc.setRemoteDescription(offer); + const answer = await pc.createAnswer(); + pc.close(); + return answer; +} + +// Helper function to generate offer using a freshly +// created RTCPeerConnection object +async function generateOffer() { + const pc = new RTCPeerConnection(); + const offer = await pc.createOffer(); + pc.close(); + return offer; +} + +// Run a test function that return a promise that should +// never be resolved. For lack of better options, +// we wait for a time out and pass the test if the +// promise doesn't resolve within that time. +function test_never_resolve(testFunc, testName) { + async_test(t => { + testFunc(t) + .then( + t.step_func(result => { + assert_unreached(`Pending promise should never be resolved. Instead it is fulfilled with: ${result}`); + }), + t.step_func(err => { + assert_unreached(`Pending promise should never be resolved. Instead it is rejected with: ${err}`); + })); + + t.step_timeout(t.step_func_done(), 100) + }, testName); +} + +// Helper function to exchange ice candidates between +// two local peer connections +function exchangeIceCandidates(pc1, pc2) { + // private function + function doExchange(localPc, remotePc) { + localPc.addEventListener('icecandidate', event => { + const { candidate } = event; + + // Guard against already closed peerconnection to + // avoid unrelated exceptions. + if (remotePc.signalingState !== 'closed') { + remotePc.addIceCandidate(candidate); + } + }); + } + + doExchange(pc1, pc2); + doExchange(pc2, pc1); +} + +// Returns a promise that resolves when a |name| event is fired. +function waitUntilEvent(obj, name) { + return new Promise(r => obj.addEventListener(name, r, {once: true})); +} + +// Returns a promise that resolves when the |transport.state| is |state| +// This should work for RTCSctpTransport, RTCDtlsTransport and RTCIceTransport. +async function waitForState(transport, state) { + while (transport.state != state) { + await waitUntilEvent(transport, 'statechange'); + } +} + +// Returns a promise that resolves when |pc.iceConnectionState| is 'connected' +// or 'completed'. +async function listenToIceConnected(pc) { + await waitForIceStateChange(pc, ['connected', 'completed']); +} + +// Returns a promise that resolves when |pc.iceConnectionState| is in one of the +// wanted states. +async function waitForIceStateChange(pc, wantedStates) { + while (!wantedStates.includes(pc.iceConnectionState)) { + await waitUntilEvent(pc, 'iceconnectionstatechange'); + } +} + +// Returns a promise that resolves when |pc.connectionState| is 'connected'. +async function listenToConnected(pc) { + while (pc.connectionState != 'connected') { + await waitUntilEvent(pc, 'connectionstatechange'); + } +} + +// Returns a promise that resolves when |pc.connectionState| is in one of the +// wanted states. +async function waitForConnectionStateChange(pc, wantedStates) { + while (!wantedStates.includes(pc.connectionState)) { + await waitUntilEvent(pc, 'connectionstatechange'); + } +} + +async function waitForIceGatheringState(pc, wantedStates) { + while (!wantedStates.includes(pc.iceGatheringState)) { + await waitUntilEvent(pc, 'icegatheringstatechange'); + } +} + +// Resolves when RTP packets have been received. +async function listenForSSRCs(t, receiver) { + while (true) { + const ssrcs = receiver.getSynchronizationSources(); + if (Array.isArray(ssrcs) && ssrcs.length > 0) { + return ssrcs; + } + await new Promise(r => t.step_timeout(r, 0)); + } +} + +// Helper function to create a pair of connected data channels. +// On success the promise resolves to an array with two data channels. +// It does the heavy lifting of performing signaling handshake, +// ICE candidate exchange, and waiting for data channel at two +// end points to open. Can do both negotiated and non-negotiated setup. +async function createDataChannelPair(t, options, + pc1 = createPeerConnectionWithCleanup(t), + pc2 = createPeerConnectionWithCleanup(t)) { + let pair = [], bothOpen; + try { + if (options.negotiated) { + pair = [pc1, pc2].map(pc => pc.createDataChannel('', options)); + bothOpen = Promise.all(pair.map(dc => new Promise((r, e) => { + dc.onopen = r; + dc.onerror = ({error}) => e(error); + }))); + } else { + pair = [pc1.createDataChannel('', options)]; + bothOpen = Promise.all([ + new Promise((r, e) => { + pair[0].onopen = r; + pair[0].onerror = ({error}) => e(error); + }), + new Promise((r, e) => pc2.ondatachannel = ({channel}) => { + pair[1] = channel; + channel.onopen = r; + channel.onerror = ({error}) => e(error); + }) + ]); + } + exchangeIceCandidates(pc1, pc2); + await exchangeOfferAnswer(pc1, pc2); + await bothOpen; + return pair; + } finally { + for (const dc of pair) { + dc.onopen = dc.onerror = null; + } + } +} + +// Wait for RTP and RTCP stats to arrive +async function waitForRtpAndRtcpStats(pc) { + // If remote stats are never reported, return after 5 seconds. + const startTime = performance.now(); + while (true) { + const report = await pc.getStats(); + const stats = [...report.values()].filter(({type}) => type.endsWith("bound-rtp")); + // Each RTP and RTCP stat has a reference + // to the matching stat in the other direction + if (stats.length && stats.every(({localId, remoteId}) => localId || remoteId)) { + break; + } + if (performance.now() > startTime + 5000) { + break; + } + } +} + +// Wait for a single message event and return +// a promise that resolve when the event fires +function awaitMessage(channel) { + const once = true; + return new Promise((resolve, reject) => { + channel.addEventListener('message', ({data}) => resolve(data), {once}); + channel.addEventListener('error', reject, {once}); + }); +} + +// Helper to convert a blob to array buffer so that +// we can read the content +async function blobToArrayBuffer(blob) { + const reader = new FileReader(); + reader.readAsArrayBuffer(blob); + return new Promise((resolve, reject) => { + reader.addEventListener('load', () => resolve(reader.result), {once: true}); + reader.addEventListener('error', () => reject(reader.error), {once: true}); + }); +} + +// Assert that two TypedArray or ArrayBuffer objects have the same byte values +function assert_equals_typed_array(array1, array2) { + const [view1, view2] = [array1, array2].map((array) => { + if (array instanceof ArrayBuffer) { + return new DataView(array); + } else { + assert_true(array.buffer instanceof ArrayBuffer, + 'Expect buffer to be instance of ArrayBuffer'); + return new DataView(array.buffer, array.byteOffset, array.byteLength); + } + }); + + assert_equals(view1.byteLength, view2.byteLength, + 'Expect both arrays to be of the same byte length'); + + const byteLength = view1.byteLength; + + for (let i = 0; i < byteLength; ++i) { + assert_equals(view1.getUint8(i), view2.getUint8(i), + `Expect byte at buffer position ${i} to be equal`); + } +} + +// These media tracks will be continually updated with deterministic "noise" in +// order to ensure UAs do not cease transmission in response to apparent +// silence. +// +// > Many codecs and systems are capable of detecting "silence" and changing +// > their behavior in this case by doing things such as not transmitting any +// > media. +// +// Source: https://w3c.github.io/webrtc-pc/#offer-answer-options +const trackFactories = { + // Share a single context between tests to avoid exceeding resource limits + // without requiring explicit destruction. + audioContext: null, + + /** + * Given a set of requested media types, determine if the user agent is + * capable of procedurally generating a suitable media stream. + * + * @param {object} requested + * @param {boolean} [requested.audio] - flag indicating whether the desired + * stream should include an audio track + * @param {boolean} [requested.video] - flag indicating whether the desired + * stream should include a video track + * + * @returns {boolean} + */ + canCreate(requested) { + const supported = { + audio: !!window.AudioContext && !!window.MediaStreamAudioDestinationNode, + video: !!HTMLCanvasElement.prototype.captureStream + }; + + return (!requested.audio || supported.audio) && + (!requested.video || supported.video); + }, + + audio() { + const ctx = trackFactories.audioContext = trackFactories.audioContext || + new AudioContext(); + const oscillator = ctx.createOscillator(); + const dst = oscillator.connect(ctx.createMediaStreamDestination()); + oscillator.start(); + return dst.stream.getAudioTracks()[0]; + }, + + video({width = 640, height = 480, signal} = {}) { + const canvas = Object.assign( + document.createElement("canvas"), {width, height} + ); + const ctx = canvas.getContext('2d'); + const stream = canvas.captureStream(); + + let count = 0; + const interval = setInterval(() => { + ctx.fillStyle = `rgb(${count%255}, ${count*count%255}, ${count%255})`; + count += 1; + ctx.fillRect(0, 0, width, height); + // Add some bouncing boxes in contrast color to add a little more noise. + const contrast = count + 128; + ctx.fillStyle = `rgb(${contrast%255}, ${contrast*contrast%255}, ${contrast%255})`; + const xpos = count % (width - 20); + const ypos = count % (height - 20); + ctx.fillRect(xpos, ypos, xpos + 20, ypos + 20); + const xpos2 = (count + width / 2) % (width - 20); + const ypos2 = (count + height / 2) % (height - 20); + ctx.fillRect(xpos2, ypos2, xpos2 + 20, ypos2 + 20); + // If signal is set (0-255), add a constant-color box of that luminance to + // the video frame at coordinates 20 to 60 in both X and Y direction. + // (big enough to avoid color bleed from surrounding video in some codecs, + // for more stable tests). + if (signal != undefined) { + ctx.fillStyle = `rgb(${signal}, ${signal}, ${signal})`; + ctx.fillRect(20, 20, 40, 40); + } + }, 100); + + if (document.body) { + document.body.appendChild(canvas); + } else { + document.addEventListener('DOMContentLoaded', () => { + document.body.appendChild(canvas); + }, {once: true}); + } + + // Implement track.stop() for performance in some tests on some platforms + const track = stream.getVideoTracks()[0]; + const nativeStop = track.stop; + track.stop = function stop() { + clearInterval(interval); + nativeStop.apply(this); + if (document.body && canvas.parentElement == document.body) { + document.body.removeChild(canvas); + } + }; + return track; + } +}; + +// Get the signal from a video element inserted by createNoiseStream +function getVideoSignal(v) { + if (v.videoWidth < 60 || v.videoHeight < 60) { + throw new Error('getVideoSignal: video too small for test'); + } + const canvas = document.createElement("canvas"); + canvas.width = canvas.height = 60; + const context = canvas.getContext('2d'); + context.drawImage(v, 0, 0); + // Extract pixel value at position 40, 40 + const pixel = context.getImageData(40, 40, 1, 1); + // Use luma reconstruction to get back original value according to + // ITU-R rec BT.709 + return (pixel.data[0] * 0.21 + pixel.data[1] * 0.72 + pixel.data[2] * 0.07); +} + +async function detectSignal(t, v, value) { + while (true) { + const signal = getVideoSignal(v).toFixed(); + // allow off-by-two pixel error (observed in some implementations) + if (value - 2 <= signal && signal <= value + 2) { + return; + } + // We would like to wait for each new frame instead here, + // but there seems to be no such callback. + await new Promise(r => t.step_timeout(r, 100)); + } +} + +// Generate a MediaStream bearing the specified tracks. +// +// @param {object} [caps] +// @param {boolean} [caps.audio] - flag indicating whether the generated stream +// should include an audio track +// @param {boolean} [caps.video] - flag indicating whether the generated stream +// should include a video track, or parameters for video +async function getNoiseStream(caps = {}) { + if (!trackFactories.canCreate(caps)) { + return navigator.mediaDevices.getUserMedia(caps); + } + const tracks = []; + + if (caps.audio) { + tracks.push(trackFactories.audio()); + } + + if (caps.video) { + tracks.push(trackFactories.video(caps.video)); + } + + return new MediaStream(tracks); +} + +// Obtain a MediaStreamTrack of kind using procedurally-generated streams (and +// falling back to `getUserMedia` when the user agent cannot generate the +// requested streams). +// Return Promise of pair of track and associated mediaStream. +// Assumes that there is at least one available device +// to generate the track. +function getTrackFromUserMedia(kind) { + return getNoiseStream({ [kind]: true }) + .then(mediaStream => { + const [track] = mediaStream.getTracks(); + return [track, mediaStream]; + }); +} + +// Obtain |count| MediaStreamTracks of type |kind| and MediaStreams. The tracks +// do not belong to any stream and the streams are empty. Returns a Promise +// resolved with a pair of arrays [tracks, streams]. +// Assumes there is at least one available device to generate the tracks and +// streams and that the getUserMedia() calls resolve. +function getUserMediaTracksAndStreams(count, type = 'audio') { + let otherTracksPromise; + if (count > 1) + otherTracksPromise = getUserMediaTracksAndStreams(count - 1, type); + else + otherTracksPromise = Promise.resolve([[], []]); + return otherTracksPromise.then(([tracks, streams]) => { + return getTrackFromUserMedia(type) + .then(([track, stream]) => { + // Remove the default stream-track relationship. + stream.removeTrack(track); + tracks.push(track); + streams.push(stream); + return [tracks, streams]; + }); + }); +} + +// Performs an offer exchange caller -> callee. +async function exchangeOffer(caller, callee) { + await caller.setLocalDescription(await caller.createOffer()); + await callee.setRemoteDescription(caller.localDescription); +} +// Performs an answer exchange caller -> callee. +async function exchangeAnswer(caller, callee) { + // Note that caller's remote description must be set first; if not, + // there's a chance that candidates from callee arrive at caller before + // it has a remote description to apply them to. + const answer = await callee.createAnswer(); + await caller.setRemoteDescription(answer); + await callee.setLocalDescription(answer); +} +async function exchangeOfferAnswer(caller, callee) { + await exchangeOffer(caller, callee); + await exchangeAnswer(caller, callee); +} + +// The returned promise is resolved with caller's ontrack event. +async function exchangeAnswerAndListenToOntrack(t, caller, callee) { + const ontrackPromise = addEventListenerPromise(t, caller, 'track'); + await exchangeAnswer(caller, callee); + return ontrackPromise; +} +// The returned promise is resolved with callee's ontrack event. +async function exchangeOfferAndListenToOntrack(t, caller, callee) { + const ontrackPromise = addEventListenerPromise(t, callee, 'track'); + await exchangeOffer(caller, callee); + return ontrackPromise; +} + +// The resolver extends a |promise| that can be resolved or rejected using |resolve| +// or |reject|. +class Resolver extends Promise { + constructor(executor) { + let resolve, reject; + super((resolve_, reject_) => { + resolve = resolve_; + reject = reject_; + if (executor) { + return executor(resolve_, reject_); + } + }); + + this._done = false; + this._resolve = resolve; + this._reject = reject; + } + + /** + * Return whether the promise is done (resolved or rejected). + */ + get done() { + return this._done; + } + + /** + * Resolve the promise. + */ + resolve(...args) { + this._done = true; + return this._resolve(...args); + } + + /** + * Reject the promise. + */ + reject(...args) { + this._done = true; + return this._reject(...args); + } +} + +function addEventListenerPromise(t, obj, type, listener) { + if (!listener) { + return waitUntilEvent(obj, type); + } + return new Promise(r => obj.addEventListener(type, + t.step_func(e => r(listener(e))), + {once: true})); +} + +function createPeerConnectionWithCleanup(t) { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + return pc; +} + +async function createTrackAndStreamWithCleanup(t, kind = 'audio') { + let constraints = {}; + constraints[kind] = true; + const stream = await getNoiseStream(constraints); + const [track] = stream.getTracks(); + t.add_cleanup(() => track.stop()); + return [track, stream]; +} + +function findTransceiverForSender(pc, sender) { + const transceivers = pc.getTransceivers(); + for (let i = 0; i < transceivers.length; ++i) { + if (transceivers[i].sender == sender) + return transceivers[i]; + } + return null; +} + +function preferCodec(transceiver, mimeType, sdpFmtpLine) { + const {codecs} = RTCRtpSender.getCapabilities(transceiver.receiver.track.kind); + // sdpFmtpLine is optional, pick the first partial match if not given. + const selectedCodecIndex = codecs.findIndex(c => { + return c.mimeType === mimeType && (c.sdpFmtpLine === sdpFmtpLine || !sdpFmtpLine); + }); + const selectedCodec = codecs[selectedCodecIndex]; + codecs.slice(selectedCodecIndex, 1); + codecs.unshift(selectedCodec); + return transceiver.setCodecPreferences(codecs); +} + +// Contains a set of values and will yell at you if you try to add a value twice. +class UniqueSet extends Set { + constructor(items) { + super(); + if (items !== undefined) { + for (const item of items) { + this.add(item); + } + } + } + + add(value, message) { + if (message === undefined) { + message = `Value '${value}' needs to be unique but it is already in the set`; + } + assert_true(!this.has(value), message); + super.add(value); + } +} + +const iceGatheringStateTransitions = async (pc, ...states) => { + for (const state of states) { + await new Promise((resolve, reject) => { + pc.addEventListener('icegatheringstatechange', () => { + if (pc.iceGatheringState == state) { + resolve(); + } else { + reject(`Unexpected gathering state: ${pc.iceGatheringState}, was expecting ${state}`); + } + }, {once: true}); + }); + } +}; + +const initialOfferAnswerWithIceGatheringStateTransitions = + async (pc1, pc2, offerOptions) => { + await pc1.setLocalDescription( + await pc1.createOffer(offerOptions)); + const pc1Transitions = + iceGatheringStateTransitions(pc1, 'gathering', 'complete'); + await pc2.setRemoteDescription(pc1.localDescription); + await pc2.setLocalDescription(await pc2.createAnswer()); + const pc2Transitions = + iceGatheringStateTransitions(pc2, 'gathering', 'complete'); + await pc1.setRemoteDescription(pc2.localDescription); + await pc1Transitions; + await pc2Transitions; + }; + +const expectNoMoreGatheringStateChanges = async (t, pc) => { + pc.onicegatheringstatechange = + t.step_func(() => { + assert_unreached( + 'Should not get an icegatheringstatechange right now!'); + }); +}; + +async function queueAWebrtcTask() { + const pc = new RTCPeerConnection(); + pc.addTransceiver('audio'); + await new Promise(r => pc.onnegotiationneeded = r); +} + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html new file mode 100644 index 0000000000..af55a0c003 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html @@ -0,0 +1,30 @@ + + + +RTCPeerConnection.prototype.iceConnectionState - disconnection + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState.https.html new file mode 100644 index 0000000000..5083be6cdf --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceConnectionState.https.html @@ -0,0 +1,396 @@ + + + +RTCPeerConnection.prototype.iceConnectionState + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html new file mode 100644 index 0000000000..6afaf0fbfb --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-iceGatheringState.html @@ -0,0 +1,244 @@ + + +RTCPeerConnection.prototype.iceGatheringState + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html new file mode 100644 index 0000000000..099fba8eaf --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html @@ -0,0 +1,277 @@ + + + +Mandatory-to-implement stats compliance (a subset of webrtc-stats) + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-ondatachannel.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-ondatachannel.html new file mode 100644 index 0000000000..08f206fb02 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-ondatachannel.html @@ -0,0 +1,374 @@ + + + +RTCPeerConnection.prototype.ondatachannel + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-onicecandidateerror.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-onicecandidateerror.https.html new file mode 100644 index 0000000000..096cc9dd1a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-onicecandidateerror.https.html @@ -0,0 +1,38 @@ + + +RTCPeerConnection.prototype.onicecandidateerror + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-onnegotiationneeded.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-onnegotiationneeded.html new file mode 100644 index 0000000000..6ede5ccebf --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-onnegotiationneeded.html @@ -0,0 +1,627 @@ + + +Test RTCPeerConnection.prototype.onnegotiationneeded + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html new file mode 100644 index 0000000000..ad92bf5fc6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html @@ -0,0 +1,71 @@ + + +RTCPeerConnection onsignalingstatechanged + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-ontrack.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-ontrack.https.html new file mode 100644 index 0000000000..ccdd29f6a5 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-ontrack.https.html @@ -0,0 +1,258 @@ + + +RTCPeerConnection.prototype.ontrack + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-operations.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-operations.https.html new file mode 100644 index 0000000000..28ae3afcd7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-operations.https.html @@ -0,0 +1,425 @@ + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-helper.js b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-helper.js new file mode 100644 index 0000000000..ed647bbe78 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-helper.js @@ -0,0 +1,153 @@ +'use strict' + +function peer(other, polite, fail = null) { + const send = (tgt, msg) => tgt.postMessage(JSON.parse(JSON.stringify(msg)), + "*"); + if (!fail) fail = e => send(window.parent, {error: `${e.name}: ${e.message}`}); + const pc = new RTCPeerConnection(); + + if (!window.assert_equals) { + window.assert_equals = (a, b, msg) => a === b || + fail(new Error(`${msg} expected ${b} but got ${a}`)); + } + + const commands = { + async addTransceiver() { + const transceiver = pc.addTransceiver("video"); + await new Promise(r => pc.addEventListener("negotiated", r, {once: true})); + if (!transceiver.currentDirection) { + // Might have just missed the negotiation train. Catch next one. + await new Promise(r => pc.addEventListener("negotiated", r, {once: true})); + } + assert_equals(transceiver.currentDirection, "sendonly", "have direction"); + return pc.getTransceivers().length; + }, + async simpleConnect() { + const p = commands.addTransceiver(); + await new Promise(r => pc.oniceconnectionstatechange = + () => pc.iceConnectionState == "connected" && r()); + return await p; + }, + async getNumTransceivers() { + return pc.getTransceivers().length; + }, + }; + + try { + pc.addEventListener("icecandidate", ({candidate}) => send(other, + {candidate})); + let makingOffer = false, ignoreIceCandidateFailures = false; + let srdAnswerPending = false; + pc.addEventListener("negotiationneeded", async () => { + try { + assert_equals(pc.signalingState, "stable", "negotiationneeded always fires in stable state"); + assert_equals(makingOffer, false, "negotiationneeded not already in progress"); + makingOffer = true; + await pc.setLocalDescription(); + assert_equals(pc.signalingState, "have-local-offer", "negotiationneeded not racing with onmessage"); + assert_equals(pc.localDescription.type, "offer", "negotiationneeded SLD worked"); + send(other, {description: pc.localDescription}); + } catch (e) { + fail(e); + } finally { + makingOffer = false; + } + }); + window.onmessage = async ({data: {description, candidate, run}}) => { + try { + if (description) { + // If we have a setRemoteDescription() answer operation pending, then + // we will be "stable" by the time the next setRemoteDescription() is + // executed, so we count this being stable when deciding whether to + // ignore the offer. + let isStable = + pc.signalingState == "stable" || + (pc.signalingState == "have-local-offer" && srdAnswerPending); + const ignoreOffer = description.type == "offer" && !polite && + (makingOffer || !isStable); + if (ignoreOffer) { + ignoreIceCandidateFailures = true; + return; + } + if (description.type == "answer") + srdAnswerPending = true; + await pc.setRemoteDescription(description); + ignoreIceCandidateFailures = false; + srdAnswerPending = false; + if (description.type == "offer") { + assert_equals(pc.signalingState, "have-remote-offer", "Remote offer"); + assert_equals(pc.remoteDescription.type, "offer", "SRD worked"); + await pc.setLocalDescription(); + assert_equals(pc.signalingState, "stable", "onmessage not racing with negotiationneeded"); + assert_equals(pc.localDescription.type, "answer", "onmessage SLD worked"); + send(other, {description: pc.localDescription}); + } else { + assert_equals(pc.remoteDescription.type, "answer", "Answer was set"); + assert_equals(pc.signalingState, "stable", "answered"); + pc.dispatchEvent(new Event("negotiated")); + } + } else if (candidate) { + try { + await pc.addIceCandidate(candidate); + } catch (e) { + if (!ignoreIceCandidateFailures) throw e; + } + } else if (run) { + send(window.parent, {[run.id]: await commands[run.cmd]() || 0}); + } + } catch (e) { + fail(e); + } + }; + } catch (e) { + fail(e); + } + return pc; +} + +async function setupPeerIframe(t, polite) { + const iframe = document.createElement("iframe"); + t.add_cleanup(() => iframe.remove()); + iframe.srcdoc = + `(${peer.toString()})(window.parent, ${polite});`; + document.documentElement.appendChild(iframe); + + const failCatcher = t.step_func(({data}) => + ("error" in data) && assert_unreached(`Error in iframe: ${data.error}`)); + window.addEventListener("message", failCatcher); + t.add_cleanup(() => window.removeEventListener("message", failCatcher)); + await new Promise(r => iframe.onload = r); + return iframe; +} + +function setupPeerTopLevel(t, other, polite) { + const pc = peer(other, polite, t.step_func(e => { throw e; })); + t.add_cleanup(() => { pc.close(); window.onmessage = null; }); +} + +let counter = 0; +async function run(target, cmd) { + const id = `result${counter++}`; + target.postMessage({run: {cmd, id}}, "*"); + return new Promise(r => window.addEventListener("message", + function listen({data}) { + if (!(id in data)) return; + window.removeEventListener("message", listen); + r(data[id]); + })); +} + +let iframe; +async function setupAB(t, politeA, politeB) { + iframe = await setupPeerIframe(t, politeB); + return setupPeerTopLevel(t, iframe.contentWindow, politeA); +} +const runA = cmd => run(window, cmd); +const runB = cmd => run(iframe.contentWindow, cmd); +const runBoth = (cmdA, cmdB = cmdA) => Promise.all([runA(cmdA), runB(cmdB)]); + +async function promise_test_both_roles(f, name) { + promise_test(async t => f(t, await setupAB(t, true, false)), name); + promise_test(async t => f(t, await setupAB(t, false, true)), + `${name} with roles reversed`); +} diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html new file mode 100644 index 0000000000..cf8bdf22e2 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html new file mode 100644 index 0000000000..6134eb2006 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation.https.html new file mode 100644 index 0000000000..d01b116162 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-perfect-negotiation.https.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-plan-b-is-not-supported.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-plan-b-is-not-supported.html new file mode 100644 index 0000000000..bde6b1b003 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-plan-b-is-not-supported.html @@ -0,0 +1,28 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-relay-canvas.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-relay-canvas.https.html new file mode 100644 index 0000000000..78df2ee82d --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-relay-canvas.https.html @@ -0,0 +1,84 @@ + + + +Relay canvas via PeerConnections + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-remote-track-mute.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-remote-track-mute.https.html new file mode 100644 index 0000000000..c280a7d44d --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-remote-track-mute.https.html @@ -0,0 +1,132 @@ + + + +RTCPeerConnection-transceivers.https.html + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-removeTrack.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-removeTrack.https.html new file mode 100644 index 0000000000..83095c085a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-removeTrack.https.html @@ -0,0 +1,338 @@ + + +RTCPeerConnection.prototype.removeTrack + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html new file mode 100644 index 0000000000..4dcce45199 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html @@ -0,0 +1,29 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce.https.html new file mode 100644 index 0000000000..45a04d3a7a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-restartIce.https.html @@ -0,0 +1,482 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setDescription-transceiver.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setDescription-transceiver.html new file mode 100644 index 0000000000..9bbab30d56 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setDescription-transceiver.html @@ -0,0 +1,295 @@ + + +RTCPeerConnection Set Session Description - Transceiver Tests + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-answer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-answer.html new file mode 100644 index 0000000000..32e2332635 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-answer.html @@ -0,0 +1,230 @@ + + +RTCPeerConnection.prototype.setLocalDescription + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-offer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-offer.html new file mode 100644 index 0000000000..88f1de5ed8 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-offer.html @@ -0,0 +1,229 @@ + + +RTCPeerConnection.prototype.setLocalDescription + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https.html new file mode 100644 index 0000000000..5a7a76319a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https.html @@ -0,0 +1,170 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-pranswer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-pranswer.html new file mode 100644 index 0000000000..01845f09b1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-pranswer.html @@ -0,0 +1,166 @@ + + +RTCPeerConnection.prototype.setLocalDescription pranswer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html new file mode 100644 index 0000000000..787edc92e7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html @@ -0,0 +1,167 @@ + + +RTCPeerConnection.prototype.setLocalDescription rollback + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription.html new file mode 100644 index 0000000000..c4671c3008 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setLocalDescription.html @@ -0,0 +1,152 @@ + + +RTCPeerConnection.prototype.setLocalDescription + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-answer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-answer.html new file mode 100644 index 0000000000..7306311b0a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-answer.html @@ -0,0 +1,123 @@ + + +RTCPeerConnection.prototype.setRemoteDescription - answer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html new file mode 100644 index 0000000000..8a86bb0c8e --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html @@ -0,0 +1,40 @@ + + +RTCPeerConnection.prototype.setRemoteDescription - legacy streams without a=msid lines + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html new file mode 100644 index 0000000000..d5acb7e1c9 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html @@ -0,0 +1,356 @@ + + +RTCPeerConnection.prototype.setRemoteDescription - offer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html new file mode 100644 index 0000000000..1f8bde0f29 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html @@ -0,0 +1,166 @@ + + +RTCPeerConnection.prototype.setRemoteDescription pranswer + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html new file mode 100644 index 0000000000..217326bfae --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html @@ -0,0 +1,115 @@ + + +RTCPeerConnection.prototype.setRemoteDescription - replaceTrack + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html new file mode 100644 index 0000000000..0e6213d708 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html @@ -0,0 +1,602 @@ + + +RTCPeerConnection.prototype.setRemoteDescription rollback + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-simulcast.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-simulcast.https.html new file mode 100644 index 0000000000..98b5d2bab7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-simulcast.https.html @@ -0,0 +1,50 @@ + + +RTCPeerConnection.prototype.setRemoteDescription rollback + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html new file mode 100644 index 0000000000..d2ee646e2c --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html @@ -0,0 +1,385 @@ + + + +RTCPeerConnection.prototype.setRemoteDescription - add/remove remote tracks + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html new file mode 100644 index 0000000000..c170f766bd --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-setRemoteDescription.html @@ -0,0 +1,171 @@ + + +RTCPeerConnection.prototype.setRemoteDescription + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-transceivers.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-transceivers.https.html new file mode 100644 index 0000000000..bb8ec2fe2b --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-transceivers.https.html @@ -0,0 +1,509 @@ + + + +RTCPeerConnection-transceivers.https.html + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-transport-stats.https.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-transport-stats.https.html new file mode 100644 index 0000000000..3dfba16c56 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-transport-stats.https.html @@ -0,0 +1,46 @@ + + +RTCPeerConnection a=setup SDP parameter test + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-videoDetectorTest.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-videoDetectorTest.html new file mode 100644 index 0000000000..6786bd49ed --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-videoDetectorTest.html @@ -0,0 +1,84 @@ + + + +RTCPeerConnection Video detector test + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnectionIceErrorEvent.html b/testing/web-platform/tests/webrtc/RTCPeerConnectionIceErrorEvent.html new file mode 100644 index 0000000000..4434cfd28b --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnectionIceErrorEvent.html @@ -0,0 +1,26 @@ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnectionIceEvent-constructor.html b/testing/web-platform/tests/webrtc/RTCPeerConnectionIceEvent-constructor.html new file mode 100644 index 0000000000..447002dca1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCPeerConnectionIceEvent-constructor.html @@ -0,0 +1,126 @@ + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpCapabilities-helper.js b/testing/web-platform/tests/webrtc/RTCRtpCapabilities-helper.js new file mode 100644 index 0000000000..fb297c35fb --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpCapabilities-helper.js @@ -0,0 +1,52 @@ +'use strict' + +// Test is based on the following editor draft: +// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +// This file depends on dictionary-helper.js which should +// be loaded from the main HTML file. + +/* + 5.2. RTCRtpSender Interface + dictionary RTCRtpCapabilities { + sequence codecs; + sequence headerExtensions; + }; + + dictionary RTCRtpCodecCapability { + DOMString mimeType; + unsigned long clockRate; + unsigned short channels; + DOMString sdpFmtpLine; + }; + + dictionary RTCRtpHeaderExtensionCapability { + DOMString uri; + }; + */ + +function validateRtpCapabilities(capabilities) { + assert_array_field(capabilities, 'codecs'); + for(const codec of capabilities.codecs) { + validateCodecCapability(codec); + } + + assert_greater_than(capabilities.codecs.length, 0, + 'Expect at least one codec capability available'); + + assert_array_field(capabilities, 'headerExtensions'); + for(const headerExt of capabilities.headerExtensions) { + validateHeaderExtensionCapability(headerExt); + } +} + +function validateCodecCapability(codec) { + assert_optional_string_field(codec, 'mimeType'); + assert_optional_unsigned_int_field(codec, 'clockRate'); + assert_optional_unsigned_int_field(codec, 'channels'); + assert_optional_string_field(codec, 'sdpFmtpLine'); +} + +function validateHeaderExtensionCapability(headerExt) { + assert_optional_string_field(headerExt, 'uri'); +} diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-codecs.html b/testing/web-platform/tests/webrtc/RTCRtpParameters-codecs.html new file mode 100644 index 0000000000..f5fa65e2ac --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-codecs.html @@ -0,0 +1,206 @@ + + +RTCRtpParameters codecs + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-encodings.html b/testing/web-platform/tests/webrtc/RTCRtpParameters-encodings.html new file mode 100644 index 0000000000..22abbb3718 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-encodings.html @@ -0,0 +1,543 @@ + + +RTCRtpParameters encodings + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-headerExtensions.html b/testing/web-platform/tests/webrtc/RTCRtpParameters-headerExtensions.html new file mode 100644 index 0000000000..7de2b75f4e --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-headerExtensions.html @@ -0,0 +1,74 @@ + + +RTCRtpParameters headerExtensions + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-helper.js b/testing/web-platform/tests/webrtc/RTCRtpParameters-helper.js new file mode 100644 index 0000000000..dd8ae0cc06 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-helper.js @@ -0,0 +1,259 @@ +'use strict'; + +// Test is based on the following editor draft: +// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +// Helper function for testing RTCRtpParameters dictionary fields + +// This file depends on dictionary-helper.js which should +// be loaded from the main HTML file. + +// An offer/answer exchange is necessary for getParameters() to have any +// negotiated parameters to return. +async function doOfferAnswerExchange(t, caller) { + const callee = new RTCPeerConnection(); + t.add_cleanup(() => callee.close()); + const offer = await caller.createOffer(); + await caller.setLocalDescription(offer); + await callee.setRemoteDescription(offer); + const answer = await callee.createAnswer(); + await callee.setLocalDescription(answer); + await caller.setRemoteDescription(answer); + + return callee; +} + +/* + Validates the RTCRtpParameters returned from RTCRtpSender.prototype.getParameters + + 5.2. RTCRtpSender Interface + getParameters + - transactionId is set to a new unique identifier, used to match this getParameters + call to a setParameters call that may occur later. + + - encodings is set to the value of the [[SendEncodings]] internal slot. + + - The headerExtensions sequence is populated based on the header extensions that + have been negotiated for sending. + + - The codecs sequence is populated based on the codecs that have been negotiated + for sending, and which the user agent is currently capable of sending. If + setParameters has removed or reordered codecs, getParameters MUST return the + shortened/reordered list. However, every time codecs are renegotiated by a + new offer/answer exchange, the list of codecs MUST be restored to the full + negotiated set, in the priority order indicated by the remote description, + in effect discarding the effects of setParameters. + + - rtcp.cname is set to the CNAME of the associated RTCPeerConnection. rtcp.reducedSize + is set to true if reduced-size RTCP has been negotiated for sending, and false otherwise. + */ +function validateSenderRtpParameters(param) { + validateRtpParameters(param); + + assert_array_field(param, 'encodings'); + for(const encoding of param.encodings) { + validateEncodingParameters(encoding); + } + + assert_not_equals(param.transactionId, undefined, + 'Expect sender param.transactionId to be set'); + + assert_not_equals(param.rtcp.cname, undefined, + 'Expect sender param.rtcp.cname to be set'); + + assert_not_equals(param.rtcp.reducedSize, undefined, + 'Expect sender param.rtcp.reducedSize to be set to either true or false'); +} + +/* + Validates the RTCRtpParameters returned from RTCRtpReceiver.prototype.getParameters + + 5.3. RTCRtpReceiver Interface + getParameters + When getParameters is called, the RTCRtpParameters dictionary is constructed + as follows: + + - The headerExtensions sequence is populated based on the header extensions that + the receiver is currently prepared to receive. + + - The codecs sequence is populated based on the codecs that the receiver is currently + prepared to receive. + + - rtcp.reducedSize is set to true if the receiver is currently prepared to receive + reduced-size RTCP packets, and false otherwise. rtcp.cname is left undefined. + + - transactionId is left undefined. + */ +function validateReceiverRtpParameters(param) { + validateRtpParameters(param); + + assert_equals(param.transactionId, undefined, + 'Expect receiver param.transactionId to be unset'); + + assert_not_equals(param.rtcp.reducedSize, undefined, + 'Expect receiver param.rtcp.reducedSize to be set'); + + assert_equals(param.rtcp.cname, undefined, + 'Expect receiver param.rtcp.cname to be unset'); +} + +/* + dictionary RTCRtpParameters { + DOMString transactionId; + sequence encodings; + sequence headerExtensions; + RTCRtcpParameters rtcp; + sequence codecs; + }; + + */ +function validateRtpParameters(param) { + assert_optional_string_field(param, 'transactionId'); + + assert_array_field(param, 'headerExtensions'); + for(const headerExt of param.headerExtensions) { + validateHeaderExtensionParameters(headerExt); + } + + assert_dict_field(param, 'rtcp'); + validateRtcpParameters(param.rtcp); + + assert_array_field(param, 'codecs'); + for(const codec of param.codecs) { + validateCodecParameters(codec); + } +} + +/* + dictionary RTCRtpEncodingParameters { + boolean active; + unsigned long maxBitrate; + + [readonly] + DOMString rid; + + double scaleResolutionDownBy; + }; + + */ +function validateEncodingParameters(encoding) { + assert_optional_boolean_field(encoding, 'active'); + assert_optional_unsigned_int_field(encoding, 'maxBitrate'); + + assert_optional_string_field(encoding, 'rid'); + assert_optional_number_field(encoding, 'scaleResolutionDownBy'); +} + +/* + dictionary RTCRtcpParameters { + [readonly] + DOMString cname; + + [readonly] + boolean reducedSize; + }; + */ +function validateRtcpParameters(rtcp) { + assert_optional_string_field(rtcp, 'cname'); + assert_optional_boolean_field(rtcp, 'reducedSize'); +} + +/* + dictionary RTCRtpHeaderExtensionParameters { + [readonly] + DOMString uri; + + [readonly] + unsigned short id; + + [readonly] + boolean encrypted; + }; + */ +function validateHeaderExtensionParameters(headerExt) { + assert_optional_string_field(headerExt, 'uri'); + assert_optional_unsigned_int_field(headerExt, 'id'); + assert_optional_boolean_field(headerExt, 'encrypted'); +} + +/* + dictionary RTCRtpCodecParameters { + [readonly] + unsigned short payloadType; + + [readonly] + DOMString mimeType; + + [readonly] + unsigned long clockRate; + + [readonly] + unsigned short channels; + + [readonly] + DOMString sdpFmtpLine; + }; + */ +function validateCodecParameters(codec) { + assert_optional_unsigned_int_field(codec, 'payloadType'); + assert_optional_string_field(codec, 'mimeType'); + assert_optional_unsigned_int_field(codec, 'clockRate'); + assert_optional_unsigned_int_field(codec, 'channels'); + assert_optional_string_field(codec, 'sdpFmtpLine'); +} + +// Helper function to test that modifying an encoding field should succeed +function test_modified_encoding(kind, field, value1, value2, desc) { + promise_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const { + sender + } = pc.addTransceiver(kind, { + sendEncodings: [{ + [field]: value1 + }] + }); + await doOfferAnswerExchange(t, pc); + + const param1 = sender.getParameters(); + validateSenderRtpParameters(param1); + const encoding1 = param1.encodings[0]; + + assert_equals(encoding1[field], value1); + encoding1[field] = value2; + + await sender.setParameters(param1); + const param2 = sender.getParameters(); + validateSenderRtpParameters(param2); + const encoding2 = param2.encodings[0]; + assert_equals(encoding2[field], value2); + }, desc + ' with RTCRtpTransceiverInit'); + + promise_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const { + sender + } = pc.addTransceiver(kind); + await doOfferAnswerExchange(t, pc); + + const initParam = sender.getParameters(); + validateSenderRtpParameters(initParam); + initParam.encodings[0][field] = value1; + await sender.setParameters(initParam); + + const param1 = sender.getParameters(); + validateSenderRtpParameters(param1); + const encoding1 = param1.encodings[0]; + + assert_equals(encoding1[field], value1); + encoding1[field] = value2; + + await sender.setParameters(param1); + const param2 = sender.getParameters(); + validateSenderRtpParameters(param2); + const encoding2 = param2.encodings[0]; + assert_equals(encoding2[field], value2); + }, desc + ' without RTCRtpTransceiverInit'); +} diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-rtcp.html b/testing/web-platform/tests/webrtc/RTCRtpParameters-rtcp.html new file mode 100644 index 0000000000..7965304520 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-rtcp.html @@ -0,0 +1,104 @@ + + +RTCRtpParameters rtcp + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpParameters-transactionId.html b/testing/web-platform/tests/webrtc/RTCRtpParameters-transactionId.html new file mode 100644 index 0000000000..a0fa0fab25 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpParameters-transactionId.html @@ -0,0 +1,190 @@ + + +RTCRtpParameters transactionId + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpReceiver-getCapabilities.html b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getCapabilities.html new file mode 100644 index 0000000000..21dcae208a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getCapabilities.html @@ -0,0 +1,39 @@ + + +RTCRtpReceiver.getCapabilities + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpReceiver-getContributingSources.https.html b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getContributingSources.https.html new file mode 100644 index 0000000000..7245d477cc --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getContributingSources.https.html @@ -0,0 +1,35 @@ + + +RTCRtpReceiver.prototype.getContributingSources + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpReceiver-getParameters.html b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getParameters.html new file mode 100644 index 0000000000..7047ce7d1f --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getParameters.html @@ -0,0 +1,73 @@ + + +RTCRtpReceiver.prototype.getParameters + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpReceiver-getStats.https.html b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getStats.https.html new file mode 100644 index 0000000000..39948ed6f7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getStats.https.html @@ -0,0 +1,145 @@ + + + +RTCRtpReceiver.prototype.getStats + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html new file mode 100644 index 0000000000..8436a44ebc --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html @@ -0,0 +1,105 @@ + + + + +RTCRtpReceiver.prototype.getSynchronizationSources + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-encode-same-track-twice.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender-encode-same-track-twice.https.html new file mode 100644 index 0000000000..568543da70 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-encode-same-track-twice.https.html @@ -0,0 +1,66 @@ + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-getCapabilities.html b/testing/web-platform/tests/webrtc/RTCRtpSender-getCapabilities.html new file mode 100644 index 0000000000..3d41c62016 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-getCapabilities.html @@ -0,0 +1,45 @@ + + +RTCRtpSender.getCapabilities + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-getStats.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender-getStats.https.html new file mode 100644 index 0000000000..62c01aafa6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-getStats.https.html @@ -0,0 +1,97 @@ + + + +RTCRtpSender.prototype.getStats + + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-replaceTrack.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender-replaceTrack.https.html new file mode 100644 index 0000000000..bec44c53e4 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-replaceTrack.https.html @@ -0,0 +1,338 @@ + + + +RTCRtpSender.prototype.replaceTrack + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-setParameters.html b/testing/web-platform/tests/webrtc/RTCRtpSender-setParameters.html new file mode 100644 index 0000000000..94c572343d --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-setParameters.html @@ -0,0 +1,52 @@ + + +RTCRtpSender.prototype.setParameters + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-setStreams.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender-setStreams.https.html new file mode 100644 index 0000000000..03ae863d0f --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-setStreams.https.html @@ -0,0 +1,127 @@ + + +RTCRtpSender.prototype.setStreams + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender-transport.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender-transport.https.html new file mode 100644 index 0000000000..cd419ebc18 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender-transport.https.html @@ -0,0 +1,152 @@ + + + +RTCRtpSender.transport + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpSender.https.html b/testing/web-platform/tests/webrtc/RTCRtpSender.https.html new file mode 100644 index 0000000000..d17115c46a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpSender.https.html @@ -0,0 +1,20 @@ + + +RTCRtpSender + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver-direction.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-direction.html new file mode 100644 index 0000000000..e76bc1fbb7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-direction.html @@ -0,0 +1,94 @@ + + +RTCRtpTransceiver.prototype.direction + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html new file mode 100644 index 0000000000..f779f5a94c --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html @@ -0,0 +1,322 @@ + + +RTCRtpTransceiver.prototype.setCodecPreferences + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stop.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stop.html new file mode 100644 index 0000000000..766b34d7b1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stop.html @@ -0,0 +1,155 @@ + + +RTCRtpTransceiver.prototype.stop + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stopping.https.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stopping.https.html new file mode 100644 index 0000000000..16be25fe13 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-stopping.https.html @@ -0,0 +1,217 @@ + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver.https.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver.https.html new file mode 100644 index 0000000000..943550d4b7 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver.https.html @@ -0,0 +1,2297 @@ + + + +RTCRtpTransceiver + + + + diff --git a/testing/web-platform/tests/webrtc/RTCSctpTransport-constructor.html b/testing/web-platform/tests/webrtc/RTCSctpTransport-constructor.html new file mode 100644 index 0000000000..484967f76b --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCSctpTransport-constructor.html @@ -0,0 +1,125 @@ + + +RTCSctpTransport constructor + + + + diff --git a/testing/web-platform/tests/webrtc/RTCSctpTransport-events.html b/testing/web-platform/tests/webrtc/RTCSctpTransport-events.html new file mode 100644 index 0000000000..57b691a9cd --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCSctpTransport-events.html @@ -0,0 +1,55 @@ + + +RTCIceTransport + + + + diff --git a/testing/web-platform/tests/webrtc/RTCSctpTransport-maxChannels.html b/testing/web-platform/tests/webrtc/RTCSctpTransport-maxChannels.html new file mode 100644 index 0000000000..b173e11c74 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCSctpTransport-maxChannels.html @@ -0,0 +1,49 @@ + + +RTCSctpTransport.prototype.maxChannels + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCSctpTransport-maxMessageSize.html b/testing/web-platform/tests/webrtc/RTCSctpTransport-maxMessageSize.html new file mode 100644 index 0000000000..9976761150 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCSctpTransport-maxMessageSize.html @@ -0,0 +1,206 @@ + + +RTCSctpTransport.prototype.maxMessageSize + + + + + diff --git a/testing/web-platform/tests/webrtc/RTCStats-helper.js b/testing/web-platform/tests/webrtc/RTCStats-helper.js new file mode 100644 index 0000000000..29d4940a8a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCStats-helper.js @@ -0,0 +1,973 @@ +'use strict'; + +// Test is based on the following editor draft: +// webrtc-pc 20171130 +// webrtc-stats 20171122 + +// This file depends on dictionary-helper.js which should +// be loaded from the main HTML file. + +/* + [webrtc-stats] + 6.1. RTCStatsType enum + enum RTCStatsType { + "codec", + "inbound-rtp", + "outbound-rtp", + "remote-inbound-rtp", + "remote-outbound-rtp", + "csrc", + "peer-connection", + "data-channel", + "transport", + "candidate-pair", + "local-candidate", + "remote-candidate", + "certificate", + "ice-server" + }; + */ +const statsValidatorTable = { + 'codec': validateCodecStats, + 'inbound-rtp': validateInboundRtpStreamStats, + 'outbound-rtp': validateOutboundRtpStreamStats, + 'remote-inbound-rtp': validateRemoteInboundRtpStreamStats, + 'remote-outbound-rtp': validateRemoteOutboundRtpStreamStats, + 'media-source': validateMediaSourceStats, + 'csrc': validateContributingSourceStats, + 'peer-connection': validatePeerConnectionStats, + 'data-channel': validateDataChannelStats, + 'transport': validateTransportStats, + 'candidate-pair': validateIceCandidatePairStats, + 'local-candidate': validateIceCandidateStats, + 'remote-candidate': validateIceCandidateStats, + 'certificate': validateCertificateStats, + 'ice-server': validateIceServerStats +}; + +// Validate that the stats objects in a stats report +// follows the respective definitions. +// Stats objects with unknown type are ignored and +// only basic validation is done. +function validateStatsReport(statsReport) { + for(const [id, stats] of statsReport.entries()) { + assert_equals(stats.id, id, + 'expect stats.id to be the same as the key in statsReport'); + + const validator = statsValidatorTable[stats.type]; + if(validator) { + validator(statsReport, stats); + } else { + validateRtcStats(statsReport, stats); + } + } +} + +// Assert that the stats report have stats objects of +// given types +function assert_stats_report_has_stats(statsReport, statsTypes) { + const hasTypes = new Set([...statsReport.values()] + .map(stats => stats.type)); + + for(const type of statsTypes) { + assert_true(hasTypes.has(type), + `Expect statsReport to contain stats object of type ${type}`); + } +} + +function findStatsFromReport(statsReport, predicate, message) { + for (const stats of statsReport.values()) { + if (predicate(stats)) { + return stats; + } + } + + assert_unreached(message || 'none of stats in statsReport satisfy given condition') +} + +// Get stats object of type that is expected to be +// found in the statsReport +function getRequiredStats(statsReport, type) { + for(const stats of statsReport.values()) { + if(stats.type === type) { + return stats; + } + } + + assert_unreached(`required stats of type ${type} is not found in stats report`); +} + +// Get stats object by the stats ID. +// This is used to retreive other stats objects +// linked to a stats object +function getStatsById(statsReport, statsId) { + assert_true(statsReport.has(statsId), + `Expect stats report to have stats object with id ${statsId}`); + + return statsReport.get(statsId); +} + +// Validate an ID field in a stats object by making sure +// that the linked stats object is found in the stats report +// and have the type field value same as expected type +// It doesn't validate the other fields of the linked stats +// as validateStatsReport already does all validations +function validateIdField(statsReport, stats, field, type) { + assert_string_field(stats, field); + const linkedStats = getStatsById(statsReport, stats[field]); + assert_equals(linkedStats.type, type, + `Expect linked stats object to have type ${type}`); +} + +function validateOptionalIdField(statsReport, stats, field, type) { + if(stats[field] !== undefined) { + validateIdField(statsReport, stats, field, type); + } +} + +/* + [webrtc-pc] + 8.4. RTCStats Dictionary + dictionary RTCStats { + required DOMHighResTimeStamp timestamp; + required RTCStatsType type; + required DOMString id; + }; + */ +function validateRtcStats(statsReport, stats) { + assert_number_field(stats, 'timestamp'); + assert_string_field(stats, 'type'); + assert_string_field(stats, 'id'); +} + +/* + [webrtc-stats] + 7.1. RTCRtpStreamStats dictionary + dictionary RTCRtpStreamStats : RTCStats { + unsigned long ssrc; + DOMString kind; + DOMString transportId; + DOMString codecId; + }; + + kind of type DOMString + Either "audio" or "video". + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCRtpStreamStats, with attributes ssrc, kind, transportId, codecId + */ +function validateRtpStreamStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_unsigned_int_field(stats, 'ssrc'); + assert_string_field(stats, 'kind'); + assert_enum_field(stats, 'kind', ['audio', 'video']) + + validateIdField(statsReport, stats, 'transportId', 'transport'); + validateIdField(statsReport, stats, 'codecId', 'codec'); + +} + +/* + [webrtc-stats] + 7.2. RTCCodecStats dictionary + dictionary RTCCodecStats : RTCStats { + required unsigned long payloadType; + RTCCodecType codecType; + required DOMString transportId; + required DOMString mimeType; + unsigned long clockRate; + unsigned long channels; + DOMString sdpFmtpLine; + }; + + enum RTCCodecType { + "encode", + "decode", + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCCodecStats, with attributes payloadType, codecType, mimeType, clockRate, channels, sdpFmtpLine + */ + +function validateCodecStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_unsigned_int_field(stats, 'payloadType'); + assert_optional_enum_field(stats, 'codecType', ['encode', 'decode']); + + validateOptionalIdField(statsReport, stats, 'transportId', 'transport'); + + assert_string_field(stats, 'mimeType'); + assert_unsigned_int_field(stats, 'clockRate'); + if (stats.kind === 'audio') { + assert_unsigned_int_field(stats, 'channels'); + } + assert_string_field(stats, 'sdpFmtpLine'); +} + +/* + [webrtc-stats] + 7.3. RTCReceivedRtpStreamStats dictionary + dictionary RTCReceivedRtpStreamStats : RTCRtpStreamStats { + unsigned long long packetsReceived; + long long packetsLost; + double jitter; + unsigned long long packetsDiscarded; + unsigned long long packetsRepaired; + unsigned long long burstPacketsLost; + unsigned long long burstPacketsDiscarded; + unsigned long burstLossCount; + unsigned long burstDiscardCount; + double burstLossRate; + double burstDiscardRate; + double gapLossRate; + double gapDiscardRate; + unsigned long framesDropped; + unsigned long partialFramesLost; + unsigned long fullFramesLost; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCReceivedRtpStreamStats, with all required attributes from its + inherited dictionaries, and also attributes packetsReceived, + packetsLost, jitter, packetsDiscarded, framesDropped + */ +function validateReceivedRtpStreamStats(statsReport, stats) { + validateRtpStreamStats(statsReport, stats); + + assert_unsigned_int_field(stats, 'packetsReceived'); + assert_unsigned_int_field(stats, 'packetsLost'); + + assert_number_field(stats, 'jitter'); + + assert_unsigned_int_field(stats, 'packetsDiscarded'); + assert_unsigned_int_field(stats, 'framesDropped'); + + assert_optional_unsigned_int_field(stats, 'packetsRepaired'); + assert_optional_unsigned_int_field(stats, 'burstPacketsLost'); + assert_optional_unsigned_int_field(stats, 'burstPacketsDiscarded'); + assert_optional_unsigned_int_field(stats, 'burstLossCount'); + assert_optional_unsigned_int_field(stats, 'burstDiscardCount'); + + assert_optional_number_field(stats, 'burstLossRate'); + assert_optional_number_field(stats, 'burstDiscardRate'); + assert_optional_number_field(stats, 'gapLossRate'); + assert_optional_number_field(stats, 'gapDiscardRate'); + + assert_optional_unsigned_int_field(stats, 'partialFramesLost'); + assert_optional_unsigned_int_field(stats, 'fullFramesLost'); +} + +/* + [webrtc-stats] + 7.4. RTCInboundRtpStreamStats dictionary + dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats { + DOMString trackIdentifier; + DOMString remoteId; + unsigned long framesDecoded; + unsigned long keyFramesDecoded; + unsigned long frameWidth; + unsigned long frameHeight; + unsigned long frameBitDepth; + double framesPerSecond; + unsigned long long qpSum; + double totalDecodeTime; + double totalInterFrameDelay; + double totalSquaredInterFrameDelay; + boolean voiceActivityFlag; + DOMHighResTimeStamp lastPacketReceivedTimestamp; + double averageRtcpInterval; + unsigned long long headerBytesReceived; + unsigned long long fecPacketsReceived; + unsigned long long fecPacketsDiscarded; + unsigned long long bytesReceived; + unsigned long long packetsFailedDecryption; + unsigned long long packetsDuplicated; + record perDscpPacketsReceived; + unsigned long nackCount; + unsigned long firCount; + unsigned long pliCount; + unsigned long sliCount; + DOMHighResTimeStamp estimatedPlayoutTimestamp; + double jitterBufferDelay; + unsigned long long jitterBufferEmittedCount; + unsigned long long totalSamplesReceived; + unsigned long long samplesDecodedWithSilk; + unsigned long long samplesDecodedWithCelt; + unsigned long long concealedSamples; + unsigned long long silentConcealedSamples; + unsigned long long concealmentEvents; + unsigned long long insertedSamplesForDeceleration; + unsigned long long removedSamplesForAcceleration; + double audioLevel; + double totalAudioEnergy; + double totalSamplesDuration; + unsigned long framesReceived; + DOMString decoderImplementation; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCInboundRtpStreamStats, with all required attributes from its inherited + dictionaries, and also attributes remoteId, framesDecoded, nackCount, framesReceived, bytesReceived, totalAudioEnergy, totalSampleDuration + */ +function validateInboundRtpStreamStats(statsReport, stats) { + validateReceivedRtpStreamStats(statsReport, stats); + assert_string_field(stats, 'trackIdentifier'); + validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp'); + assert_unsigned_int_field(stats, 'framesDecoded'); + assert_optional_unsigned_int_field(stats, 'keyFramesDecoded'); + assert_optional_unsigned_int_field(stats, 'frameWidth'); + assert_optional_unsigned_int_field(stats, 'frameHeight'); + assert_optional_unsigned_int_field(stats, 'frameBitDepth'); + assert_optional_number_field(stats, 'framesPerSecond'); + assert_optional_unsigned_int_field(stats, 'qpSum'); + assert_optional_number_field(stats, 'totalDecodeTime'); + assert_optional_number_field(stats, 'totalInterFrameDelay'); + assert_optional_number_field(stats, 'totalSquaredInterFrameDelay'); + + assert_optional_boolean_field(stats, 'voiceActivityFlag'); + + assert_optional_number_field(stats, 'lastPacketReceivedTimeStamp'); + assert_optional_number_field(stats, 'averageRtcpInterval'); + + assert_optional_unsigned_int_field(stats, 'fecPacketsReceived'); + assert_optional_unsigned_int_field(stats, 'fecPacketsDiscarded'); + assert_unsigned_int_field(stats, 'bytesReceived'); + assert_optional_unsigned_int_field(stats, 'packetsFailedDecryption'); + assert_optional_unsigned_int_field(stats, 'packetsDuplicated'); + + assert_optional_dict_field(stats, 'perDscpPacketsReceived'); + if (stats['perDscpPacketsReceived']) { + Object.keys(stats['perDscpPacketsReceived']) + .forEach(k => + assert_equals(typeof k, 'string', 'Expect keys of perDscpPacketsReceived to be strings') + ); + Object.values(stats['perDscpPacketsReceived']) + .forEach(v => + assert_true(Number.isInteger(v) && (v >= 0), 'Expect values of perDscpPacketsReceived to be strings') + ); + } + + assert_unsigned_int_field(stats, 'nackCount'); + + assert_optional_unsigned_int_field(stats, 'firCount'); + assert_optional_unsigned_int_field(stats, 'pliCount'); + assert_optional_unsigned_int_field(stats, 'sliCount'); + + assert_optional_number_field(stats, 'estimatedPlayoutTimestamp'); + assert_optional_number_field(stats, 'jitterBufferDelay'); + assert_optional_unsigned_int_field(stats, 'jitterBufferEmittedCount'); + assert_optional_unsigned_int_field(stats, 'totalSamplesReceived'); + assert_optional_unsigned_int_field(stats, 'samplesDecodedWithSilk'); + assert_optional_unsigned_int_field(stats, 'samplesDecodedWithCelt'); + assert_optional_unsigned_int_field(stats, 'concealedSamples'); + assert_optional_unsigned_int_field(stats, 'silentConcealedSamples'); + assert_optional_unsigned_int_field(stats, 'concealmentEvents'); + assert_optional_unsigned_int_field(stats, 'insertedSamplesForDeceleration'); + assert_optional_unsigned_int_field(stats, 'removedSamplesForAcceleration'); + assert_optional_number_field(stats, 'audioLevel'); + assert_optional_number_field(stats, 'totalAudioEnergy'); + assert_optional_number_field(stats, 'totalSamplesDuration'); + assert_unsigned_int_field(stats, 'framesReceived'); + assert_optional_string_field(stats, 'decoderImplementation'); + assert_optional_boolean_field(stats, 'powerEfficientDecoder'); +} + +/* + [webrtc-stats] + 7.5. RTCRemoteInboundRtpStreamStats dictionary + dictionary RTCRemoteInboundRtpStreamStats : RTCReceivedRtpStreamStats { + DOMString localId; + double roundTripTime; + double totalRoundTripTime; + double fractionLost; + unsigned long long reportsReceived; + unsigned long long roundTripTimeMeasurements; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCRemoteInboundRtpStreamStats, with all required attributes from its + inherited dictionaries, and also attributes localId, roundTripTime + */ +function validateRemoteInboundRtpStreamStats(statsReport, stats) { + validateReceivedRtpStreamStats(statsReport, stats); + + validateIdField(statsReport, stats, 'localId', 'outbound-rtp'); + assert_number_field(stats, 'roundTripTime'); + assert_optional_number_field(stats, 'totalRoundTripTime'); + assert_optional_number_field(stats, 'fractionLost'); + assert_optional_unsigned_int_field(stats, 'reportsReceived'); + assert_optional_unsigned_int_field(stats, 'roundTripTimeMeasurements'); +} + +/* + [webrtc-stats] + 7.6. RTCSentRtpStreamStats dictionary + dictionary RTCSentRtpStreamStats : RTCRtpStreamStats { + unsigned long packetsSent; + unsigned long long bytesSent; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCSentRtpStreamStats, with all required attributes from its inherited + dictionaries, and also attributes packetsSent, bytesSent + */ +function validateSentRtpStreamStats(statsReport, stats) { + validateRtpStreamStats(statsReport, stats); + + assert_unsigned_int_field(stats, 'packetsSent'); + assert_unsigned_int_field(stats, 'bytesSent'); +} + +/* + [webrtc-stats] + 7.7. RTCOutboundRtpStreamStats dictionary + dictionary RTCOutboundRtpStreamStats : RTCSentRtpStreamStats { + DOMString mediaSourceId; + DOMString remoteId; + DOMString rid; + DOMHighResTimeStamp lastPacketSentTimestamp; + unsigned long long headerBytesSent; + unsigned long packetsDiscardedOnSend; + unsigned long long bytesDiscardedOnSend; + unsigned long fecPacketsSent; + unsigned long long retransmittedPacketsSent; + unsigned long long retransmittedBytesSent; + double targetBitrate; + unsigned long long totalEncodedBytesTarget; + unsigned long frameWidth; + unsigned long frameHeight; + unsigned long frameBitDepth; + double framesPerSecond; + unsigned long framesSent; + unsigned long hugeFramesSent; + unsigned long framesEncoded; + unsigned long keyFramesEncoded; + unsigned long framesDiscardedOnSend; + unsigned long long qpSum; + unsigned long long totalSamplesSent; + unsigned long long samplesEncodedWithSilk; + unsigned long long samplesEncodedWithCelt; + boolean voiceActivityFlag; + double totalEncodeTime; + double totalPacketSendDelay; + double averageRtcpInterval; + RTCQualityLimitationReason qualityLimitationReason; + record qualityLimitationDurations; + unsigned long qualityLimitationResolutionChanges; + record perDscpPacketsSent; + unsigned long nackCount; + unsigned long firCount; + unsigned long pliCount; + unsigned long sliCount; + DOMString encoderImplementation; + }; + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCOutboundRtpStreamStats, with all required attributes from its + inherited dictionaries, and also attributes remoteId, framesEncoded, nackCount, framesSent + */ +function validateOutboundRtpStreamStats(statsReport, stats) { + validateSentRtpStreamStats(statsReport, stats) + + validateOptionalIdField(statsReport, stats, 'mediaSourceId', 'media-source'); + validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp'); + + assert_optional_string_field(stats, 'rid'); + + assert_optional_number_field(stats, 'lastPacketSentTimestamp'); + assert_optional_unsigned_int_field(stats, 'headerBytesSent'); + assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend'); + assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend'); + assert_optional_unsigned_int_field(stats, 'fecPacketsSent'); + assert_optional_unsigned_int_field(stats, 'retransmittedPacketsSent'); + assert_optional_unsigned_int_field(stats, 'retransmittedBytesSent'); + assert_optional_number_field(stats, 'targetBitrate'); + assert_optional_unsigned_int_field(stats, 'totalEncodedBytesTarget'); + if (stats['kind'] === 'video') { + assert_optional_unsigned_int_field(stats, 'frameWidth'); + assert_optional_unsigned_int_field(stats, 'frameHeight'); + assert_optional_unsigned_int_field(stats, 'frameBitDepth'); + assert_optional_number_field(stats, 'framesPerSecond'); + assert_unsigned_int_field(stats, 'framesSent'); + assert_optional_unsigned_int_field(stats, 'hugeFramesSent'); + assert_unsigned_int_field(stats, 'framesEncoded'); + assert_optional_unsigned_int_field(stats, 'keyFramesEncoded'); + assert_optional_unsigned_int_field(stats, 'framesDiscardedOnSend'); + assert_optional_unsigned_int_field(stats, 'qpSum'); + } else if (stats['kind'] === 'audio') { + assert_optional_unsigned_int_field(stats, 'totalSamplesSent'); + assert_optional_unsigned_int_field(stats, 'samplesEncodedWithSilk'); + assert_optional_unsigned_int_field(stats, 'samplesEncodedWithCelt'); + assert_optional_boolean_field(stats, 'voiceActivityFlag'); + } + assert_optional_number_field(stats, 'totalEncodeTime'); + assert_optional_number_field(stats, 'totalPacketSendDelay'); + assert_optional_number_field(stats, 'averageRTCPInterval'); + + if (stats['kind'] === 'video') { + assert_optional_enum_field(stats, 'qualityLimitationReason', ['none', 'cpu', 'bandwidth', 'other']); + + assert_optional_dict_field(stats, 'qualityLimitationDurations'); + if (stats['qualityLimitationDurations']) { + Object.keys(stats['qualityLimitationDurations']) + .forEach(k => + assert_equals(typeof k, 'string', 'Expect keys of qualityLimitationDurations to be strings') + ); + Object.values(stats['qualityLimitationDurations']) + .forEach(v => + assert_equals(typeof num, 'number', 'Expect values of qualityLimitationDurations to be numbers') + ); + } + + assert_optional_unsigned_int_field(stats, 'qualityLimitationResolutionChanges'); + } + assert_unsigned_int_field(stats, 'nackCount'); + assert_optional_dict_field(stats, 'perDscpPacketsSent'); + if (stats['perDscpPacketsSent']) { + Object.keys(stats['perDscpPacketsSent']) + .forEach(k => + assert_equals(typeof k, 'string', 'Expect keys of perDscpPacketsSent to be strings') + ); + Object.values(stats['perDscpPacketsSent']) + .forEach(v => + assert_true(Number.isInteger(v) && (v >= 0), 'Expect values of perDscpPacketsSent to be strings') + ); + } + + assert_optional_unsigned_int_field(stats, 'firCount'); + assert_optional_unsigned_int_field(stats, 'pliCount'); + assert_optional_unsigned_int_field(stats, 'sliCount'); + assert_optional_string_field(stats, 'encoderImplementation'); + assert_optional_boolean_field(stats, 'powerEfficientEncoder'); + assert_optional_string_field(stats, 'scalabilityMode'); +} + +/* + [webrtc-stats] + 7.8. RTCRemoteOutboundRtpStreamStats dictionary + dictionary RTCRemoteOutboundRtpStreamStats : RTCSentRtpStreamStats { + DOMString localId; + DOMHighResTimeStamp remoteTimestamp; + unsigned long long reportsSent; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCRemoteOutboundRtpStreamStats, with all required attributes from its + inherited dictionaries, and also attributes localId, remoteTimestamp + */ +function validateRemoteOutboundRtpStreamStats(statsReport, stats) { + validateSentRtpStreamStats(statsReport, stats); + + validateIdField(statsReport, stats, 'localId', 'inbound-rtp'); + assert_number_field(stats, 'remoteTimeStamp'); + assert_optional_unsigned_int_field(stats, 'reportsSent'); +} + +/* + [webrtc-stats] + 7.11 RTCMediaSourceStats dictionary + dictionary RTCMediaSourceStats : RTCStats { + DOMString trackIdentifier; + DOMString kind; + }; + + dictionary RTCAudioSourceStats : RTCMediaSourceStats { + double audioLevel; + double totalAudioEnergy; + double totalSamplesDuration; + double echoReturnLoss; + double echoReturnLossEnhancement; + }; + + dictionary RTCVideoSourceStats : RTCMediaSourceStats { + unsigned long width; + unsigned long height; + unsigned long bitDepth; + unsigned long frames; + // see https://github.com/w3c/webrtc-stats/issues/540 + double framesPerSecond; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + RTCMediaSourceStats with attributes trackIdentifier, kind + RTCAudioSourceStats, with all required attributes from its inherited dictionaries and totalAudioEnergy, totalSamplesDuration + RTCVideoSourceStats, with all required attributes from its inherited dictionaries and width, height, framesPerSecond +*/ +function validateMediaSourceStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + assert_string_field(stats, 'trackIdentifier'); + assert_enum_field(stats, 'kind', ['audio', 'video']); + + if (stats.kind === 'audio') { + assert_optional_number_field(stats, 'audioLevel'); + assert_number_field(stats, 'totalAudioEnergy'); + assert_number_field(stats, 'totalSamplesDuration'); + assert_optional_number_field(stats, 'echoReturnLoss'); + assert_optional_number_field(stats, 'echoReturnLossEnhancement'); + } else if (stats.kind === 'video') { + assert_unsigned_int_field(stats, 'width'); + assert_unsigned_int_field(stats, 'height'); + assert_optional_unsigned_int_field(stats, 'bitDpeth'); + assert_optional_unsigned_int_field(stats, 'frames'); + assert_number_field(stats, 'framesPerSecond'); + } +} + +/* + [webrtc-stats] + 7.9. RTCRTPContributingSourceStats + dictionary RTCRTPContributingSourceStats : RTCStats { + unsigned long contributorSsrc; + DOMString inboundRtpStreamId; + unsigned long packetsContributedTo; + double audioLevel; + }; + */ +function validateContributingSourceStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_optional_unsigned_int_field(stats, 'contributorSsrc'); + + validateOptionalIdField(statsReport, stats, 'inboundRtpStreamId', 'inbound-rtp'); + assert_optional_unsigned_int_field(stats, 'packetsContributedTo'); + assert_optional_number_field(stats, 'audioLevel'); +} + +/* + [webrtc-stats] + 7.10. RTCPeerConnectionStats dictionary + dictionary RTCPeerConnectionStats : RTCStats { + unsigned long dataChannelsOpened; + unsigned long dataChannelsClosed; + unsigned long dataChannelsRequested; + unsigned long dataChannelsAccepted; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCPeerConnectionStats, with attributes dataChannelsOpened, dataChannelsClosed + */ +function validatePeerConnectionStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_unsigned_int_field(stats, 'dataChannelsOpened'); + assert_unsigned_int_field(stats, 'dataChannelsClosed'); + assert_optional_unsigned_int_field(stats, 'dataChannelsRequested'); + assert_optional_unsigned_int_field(stats, 'dataChannelsAccepted'); +} + +/* + [webrtc-stats] + 7.13. RTCDataChannelStats dictionary + dictionary RTCDataChannelStats : RTCStats { + DOMString label; + DOMString protocol; + // see https://github.com/w3c/webrtc-stats/issues/541 + unsigned short dataChannelIdentifier; + DOMString transportId; + RTCDataChannelState state; + unsigned long messagesSent; + unsigned long long bytesSent; + unsigned long messagesReceived; + unsigned long long bytesReceived; + }; + + [webrtc-pc] + 6.2. RTCDataChannel + enum RTCDataChannelState { + "connecting", + "open", + "closing", + "closed" + }; + + 8.6. Mandatory To Implement Stats + - RTCDataChannelStats, with attributes label, protocol, datachannelIdentifier, state, + messagesSent, bytesSent, messagesReceived, bytesReceived + */ +function validateDataChannelStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_string_field(stats, 'label'); + assert_string_field(stats, 'protocol'); + assert_unsigned_int_field(stats, 'dataChannelIdentifier'); + + validateOptionalIdField(statsReport, stats, 'transportId', 'transport'); + + assert_enum_field(stats, 'state', + ['connecting', 'open', 'closing', 'closed']); + + assert_unsigned_int_field(stats, 'messagesSent'); + assert_unsigned_int_field(stats, 'bytesSent'); + assert_unsigned_int_field(stats, 'messagesReceived'); + assert_unsigned_int_field(stats, 'bytesReceived'); +} + +/* + [webrtc-stats] + 7.14. RTCTransportStats dictionary + dictionary RTCTransportStats : RTCStats { + unsigned long long packetsSent; + unsigned long long packetsReceived; + unsigned long long bytesSent; + unsigned long long bytesReceived; + DOMString rtcpTransportStatsId; + RTCIceRole iceRole; + RTCDtlsTransportState dtlsState; + DOMString selectedCandidatePairId; + DOMString localCertificateId; + DOMString remoteCertificateId; + DOMString tlsVersion; + DOMString dtlsCipher; + DOMString srtpCipher; + DOMString tlsGroup; + unsigned long selectedCandidatePairChanges; + }; + + [webrtc-pc] + 5.5. RTCDtlsTransportState Enum + enum RTCDtlsTransportState { + "new", + "connecting", + "connected", + "closed", + "failed" + }; + + 5.6. RTCIceRole Enum + enum RTCIceRole { + "unknown", + "controlling", + "controlled" + }; + + 8.6. Mandatory To Implement Stats + - RTCTransportStats, with attributes bytesSent, bytesReceived, + selectedCandidatePairId, localCertificateId, + remoteCertificateId + */ +function validateTransportStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_optional_unsigned_int_field(stats, 'packetsSent'); + assert_optional_unsigned_int_field(stats, 'packetsReceived'); + assert_unsigned_int_field(stats, 'bytesSent'); + assert_unsigned_int_field(stats, 'bytesReceived'); + + validateOptionalIdField(statsReport, stats, 'rtcpTransportStatsId', + 'transport'); + + assert_optional_enum_field(stats, 'iceRole', + ['unknown', 'controlling', 'controlled']); + + assert_optional_enum_field(stats, 'dtlsState', + ['new', 'connecting', 'connected', 'closed', 'failed']); + + validateIdField(statsReport, stats, 'selectedCandidatePairId', 'candidate-pair'); + validateIdField(statsReport, stats, 'localCertificateId', 'certificate'); + validateIdField(statsReport, stats, 'remoteCertificateId', 'certificate'); + assert_optional_string_field(stats, 'tlsVersion'); + assert_optional_string_field(stats, 'dtlsCipher'); + assert_optional_string_field(stats, 'srtpCipher'); + assert_optional_string_field(stats, 'tlsGroup'); + assert_optional_unsigned_int_field(stats, 'selectedCandidatePairChanges'); +} + +/* + [webrtc-stats] + 7.15. RTCIceCandidateStats dictionary + dictionary RTCIceCandidateStats : RTCStats { + required DOMString transportId; + DOMString? address; + long port; + DOMString protocol; + RTCIceCandidateType candidateType; + long priority; + DOMString url; + DOMString relayProtocol; + }; + + [webrtc-pc] + 4.8.1.3. RTCIceCandidateType Enum + enum RTCIceCandidateType { + "host", + "srflx", + "prflx", + "relay" + }; + + 8.6. Mandatory To Implement Stats + - RTCIceCandidateStats, with attributes address, port, protocol, candidateType, url + */ +function validateIceCandidateStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + validateIdField(statsReport, stats, 'transportId', 'transport'); + // The address is mandatory to implement, but is allowed to be null + // when hidden for privacy reasons. + if (stats.address != null) { + // Departure from strict spec reading: + // This field is populated in a racy manner in Chrome. + // We allow it to be present or not present for the time being. + // TODO(https://bugs.chromium.org/1092721): Become consistent. + assert_optional_string_field(stats, 'address'); + } + assert_unsigned_int_field(stats, 'port'); + assert_string_field(stats, 'protocol'); + + assert_enum_field(stats, 'candidateType', + ['host', 'srflx', 'prflx', 'relay']); + + assert_optional_int_field(stats, 'priority'); + // The url field is mandatory for local candidates gathered from + // a STUN or TURN server, and MUST NOT be present otherwise. + // TODO(hta): Improve checking. + assert_optional_string_field(stats, 'url'); + assert_optional_string_field(stats, 'relayProtocol'); +} + +/* + [webrtc-stats] + 7.16. RTCIceCandidatePairStats dictionary + dictionary RTCIceCandidatePairStats : RTCStats { + DOMString transportId; + DOMString localCandidateId; + DOMString remoteCandidateId; + RTCStatsIceCandidatePairState state; + boolean nominated; + unsigned long packetsSent; + unsigned long packetsReceived; + unsigned long long bytesSent; + unsigned long long bytesReceived; + DOMHighResTimeStamp lastPacketSentTimestamp; + DOMHighResTimeStamp lastPacketReceivedTimestamp; + DOMHighResTimeStamp firstRequestTimestamp; + DOMHighResTimeStamp lastRequestTimestamp; + DOMHighResTimeStamp lastResponseTimestamp; + double totalRoundTripTime; + double currentRoundTripTime; + double availableOutgoingBitrate; + double availableIncomingBitrate; + unsigned long circuitBreakerTriggerCount; + unsigned long long requestsReceived; + unsigned long long requestsSent; + unsigned long long responsesReceived; + unsigned long long responsesSent; + unsigned long long retransmissionsReceived; + unsigned long long retransmissionsSent; + unsigned long long consentRequestsSent; + DOMHighResTimeStamp consentExpiredTimestamp; + unsigned long packetsDiscardedOnSend; + unsigned long long bytesDiscardedOnSend; }; + + enum RTCStatsIceCandidatePairState { + "frozen", + "waiting", + "in-progress", + "failed", + "succeeded" + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCIceCandidatePairStats, with attributes transportId, localCandidateId, + remoteCandidateId, state, nominated, bytesSent, bytesReceived, totalRoundTripTime, currentRoundTripTime + // not including priority per https://github.com/w3c/webrtc-pc/issues/2457 + */ +function validateIceCandidatePairStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + validateIdField(statsReport, stats, 'transportId', 'transport'); + validateIdField(statsReport, stats, 'localCandidateId', 'local-candidate'); + validateIdField(statsReport, stats, 'remoteCandidateId', 'remote-candidate'); + + assert_enum_field(stats, 'state', + ['frozen', 'waiting', 'in-progress', 'failed', 'succeeded']); + + assert_boolean_field(stats, 'nominated'); + assert_optional_unsigned_int_field(stats, 'packetsSent'); + assert_optional_unsigned_int_field(stats, 'packetsReceived'); + assert_unsigned_int_field(stats, 'bytesSent'); + assert_unsigned_int_field(stats, 'bytesReceived'); + + assert_optional_number_field(stats, 'lastPacketSentTimestamp'); + assert_optional_number_field(stats, 'lastPacketReceivedTimestamp'); + assert_optional_number_field(stats, 'firstRequestTimestamp'); + assert_optional_number_field(stats, 'lastRequestTimestamp'); + assert_optional_number_field(stats, 'lastResponseTimestamp'); + + assert_number_field(stats, 'totalRoundTripTime'); + assert_number_field(stats, 'currentRoundTripTime'); + + assert_optional_number_field(stats, 'availableOutgoingBitrate'); + assert_optional_number_field(stats, 'availableIncomingBitrate'); + + assert_optional_unsigned_int_field(stats, 'circuitBreakerTriggerCount'); + assert_optional_unsigned_int_field(stats, 'requestsReceived'); + assert_optional_unsigned_int_field(stats, 'requestsSent'); + assert_optional_unsigned_int_field(stats, 'responsesReceived'); + assert_optional_unsigned_int_field(stats, 'responsesSent'); + assert_optional_unsigned_int_field(stats, 'retransmissionsReceived'); + assert_optional_unsigned_int_field(stats, 'retransmissionsSent'); + assert_optional_unsigned_int_field(stats, 'consentRequestsSent'); + assert_optional_number_field(stats, 'consentExpiredTimestamp'); + assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend'); + assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend'); +} + +/* + [webrtc-stats] + 7.17. RTCCertificateStats dictionary + dictionary RTCCertificateStats : RTCStats { + DOMString fingerprint; + DOMString fingerprintAlgorithm; + DOMString base64Certificate; + DOMString issuerCertificateId; + }; + + [webrtc-pc] + 8.6. Mandatory To Implement Stats + - RTCCertificateStats, with attributes fingerprint, fingerprintAlgorithm, + base64Certificate, issuerCertificateId + */ +function validateCertificateStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_string_field(stats, 'fingerprint'); + assert_string_field(stats, 'fingerprintAlgorithm'); + assert_string_field(stats, 'base64Certificate'); + assert_optional_string_field(stats, 'issuerCertificateId'); +} + +/* + [webrtc-stats] + 7.30. RTCIceServerStats dictionary + dictionary RTCIceServerStats : RTCStats { + DOMString url; + long port; + DOMString protocol; + unsigned long totalRequestsSent; + unsigned long totalResponsesReceived; + double totalRoundTripTime; + }; +*/ +function validateIceServerStats(statsReport, stats) { + validateRtcStats(statsReport, stats); + + assert_optional_string_field(stats, 'url'); + assert_optional_int_field(stats, 'port'); + assert_optional_string_field(stats, 'protocol'); + assert_optional_unsigned_int_field(stats, 'totalRequestsSent'); + assert_optional_unsigned_int_field(stats, 'totalResponsesReceived'); + assert_optional_number_field(stats, 'totalRoundTripTime'); +} diff --git a/testing/web-platform/tests/webrtc/RTCTrackEvent-constructor.html b/testing/web-platform/tests/webrtc/RTCTrackEvent-constructor.html new file mode 100644 index 0000000000..c9105e693a --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCTrackEvent-constructor.html @@ -0,0 +1,159 @@ + + +RTCTrackEvent constructor + + + diff --git a/testing/web-platform/tests/webrtc/RTCTrackEvent-fire.html b/testing/web-platform/tests/webrtc/RTCTrackEvent-fire.html new file mode 100644 index 0000000000..9435d7b6e5 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RTCTrackEvent-fire.html @@ -0,0 +1,168 @@ + + +Change of msid in remote description should trigger related track events + + + diff --git a/testing/web-platform/tests/webrtc/RollbackEvents.https.html b/testing/web-platform/tests/webrtc/RollbackEvents.https.html new file mode 100644 index 0000000000..25c83842c9 --- /dev/null +++ b/testing/web-platform/tests/webrtc/RollbackEvents.https.html @@ -0,0 +1,231 @@ + + + + + diff --git a/testing/web-platform/tests/webrtc/coverage/RTCDTMFSender.txt b/testing/web-platform/tests/webrtc/coverage/RTCDTMFSender.txt new file mode 100644 index 0000000000..aa30021323 --- /dev/null +++ b/testing/web-platform/tests/webrtc/coverage/RTCDTMFSender.txt @@ -0,0 +1,122 @@ +Coverage is based on the following editor draft: +https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +7. insertDTMF + + [Trivial] + - The tones parameter is treated as a series of characters. + + [RTCDTMFSender-insertDTMF] + - The characters 0 through 9, A through D, #, and * generate the associated + DTMF tones. + + [RTCDTMFSender-insertDTMF] + - The characters a to d MUST be normalized to uppercase on entry and are equivalent + to A to D. + + [RTCDTMFSender-insertDTMF] + - As noted in [RTCWEB-AUDIO] Section 3, support for the characters 0 through 9, + A through D, #, and * are required. + + [RTCDTMFSender-insertDTMF] + - The character ',' MUST be supported, and indicates a delay of 2 seconds before + processing the next character in the tones parameter. + + [RTCDTMFSender-insertDTMF] + - All other characters (and only those other characters) MUST + be considered unrecognized. + + [Trivial] + - The duration parameter indicates the duration in ms to use for each character passed + in the tones parameters. + + [RTCDTMFSender-ontonechange] + - The duration cannot be more than 6000 ms or less than 40 ms. + + [RTCDTMFSender-ontonechange] + - The default duration is 100 ms for each tone. + + [RTCDTMFSender-ontonechange] + - The interToneGap parameter indicates the gap between tones in ms. The user agent + clamps it to at least 30 ms. The default value is 70 ms. + + [Untestable] + - The browser MAY increase the duration and interToneGap times to cause the times + that DTMF start and stop to align with the boundaries of RTP packets but it MUST + not increase either of them by more than the duration of a single RTP audio packet. + + [Trivial] + When the insertDTMF() method is invoked, the user agent MUST run the following steps: + + [Trivial] + 1. let sender be the RTCRtpSender used to send DTMF. + + [Trivial] + 2. Let transceiver be the RTCRtpTransceiver object associated with sender. + + [RTCDTMFSender-insertDTMF] + 3. If transceiver.stopped is true, throw an InvalidStateError. + + [RTCDTMFSender-insertDTMF] + 4. If transceiver.currentDirection is recvonly or inactive, throw an + InvalidStateError. + + [Trivial] + 5. Let tones be the method's first argument. + + [RTCDTMFSender-insertDTMF] + 6. If tones contains any unrecognized characters, throw an InvalidCharacterError. + + [RTCDTMFSender-insertDTMF] + 7. Set the object's toneBuffer attribute to tones. + + [RTCDTMFSender-ontonechange] + 8. If the value of the duration parameter is less than 40, set it to 40. + + [RTCDTMFSender-ontonechange-long] + If, on the other hand, the value is greater than 6000, set it to 6000. + + [RTCDTMFSender-ontonechange] + 9. If the value of the interToneGap parameter is less than 30, set it to 30. + + [RTCDTMFSender-ontonechange] + 10. If toneBuffer is an empty string, abort these steps. + + [RTCDTMFSender-ontonechange] + 11. If a Playout task is scheduled to be run; abort these steps; + + [RTCDTMFSender-ontonechange] + otherwise queue a task that runs the following steps (Playout task): + + [RTCDTMFSender-ontonechange] + 1. If transceiver.stopped is true, abort these steps. + + [RTCDTMFSender-ontonechange] + 2. If transceiver.currentDirection is recvonly or inactive, abort these steps. + + [RTCDTMFSender-ontonechange] + 3. If toneBuffer is an empty string, fire an event named tonechange with an + empty string at the RTCDTMFSender object and abort these steps. + + [RTCDTMFSender-ontonechange] + 4. Remove the first character from toneBuffer and let that character be tone. + + [Untestable] + 5. Start playout of tone for duration ms on the associated RTP media stream, + using the appropriate codec. + + [RTCDTMFSender-ontonechange] + 6. Queue a task to be executed in duration + interToneGap ms from now that + runs the steps labelled Playout task. + + [RTCDTMFSender-ontonechange] + 7. Fire an event named tonechange with a string consisting of tone at the + RTCDTMFSender object. + +Coverage Report + + Tested 31 + Not Tested 0 + Untestable 1 + + Total 32 diff --git a/testing/web-platform/tests/webrtc/coverage/identity.txt b/testing/web-platform/tests/webrtc/coverage/identity.txt new file mode 100644 index 0000000000..0d1bcca7ed --- /dev/null +++ b/testing/web-platform/tests/webrtc/coverage/identity.txt @@ -0,0 +1,220 @@ +Coverage is based on the following editor draft: +https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +9.3 Requesting Identity Assertions + + [Trivial] + The identity assertion request process is triggered by a call to createOffer, + createAnswer, or getIdentityAssertion. When these calls are invoked and an + identity provider has been set, the following steps are executed: + + [RTCPeerConnection-getIdentityAssertion] + 1. The RTCPeerConnection instantiates an IdP as described in Identity Provider + Selection and Registering an IdP Proxy. If the IdP cannot be loaded, instantiated, + or the IdP proxy is not registered, this process fails. + + [RTCPeerConnection-getIdentityAssertion] + 2. The RTCPeerConnection invokes the generateAssertion method on the + RTCIdentityProvider methods registered by the IdP. + + [RTCPeerConnection-getIdentityAssertion] + The RTCPeerConnection generates the contents parameter to this method as + described in [RTCWEB-SECURITY-ARCH]. The value of contents includes the + fingerprint of the certificate that was selected or generated during the + construction of the RTCPeerConnection. The origin parameter contains the + origin of the script that calls the RTCPeerConnection method that triggers + this behavior. The usernameHint value is the same value that is provided + to setIdentityProvider, if any such value was provided. + + [RTCPeerConnection-getIdentityAssertion] + 3. The IdP proxy returns a Promise to the RTCPeerConnection. The IdP proxy is + expected to generate the identity assertion asynchronously. + + [RTCPeerConnection-getIdentityAssertion] + If the user has been authenticated by the IdP, and the IdP is able to generate + an identity assertion, the IdP resolves the promise with an identity assertion + in the form of an RTCIdentityAssertionResult . + + [RTCPeerConnection-getIdentityAssertion] + This step depends entirely on the IdP. The methods by which an IdP authenticates + users or generates assertions is not specified, though they could involve + interacting with the IdP server or other servers. + + [RTCPeerConnection-getIdentityAssertion] + 4. If the IdP proxy produces an error or returns a promise that does not resolve + to a valid RTCIdentityValidationResult (see 9.5 IdP Error Handling), then + identity validation fails. + + [Untestable] + 5. The RTCPeerConnection MAY store the identity assertion for use with future + offers or answers. If a fresh identity assertion is needed for any reason, + applications can create a new RTCPeerConnection. + + [RTCPeerConnection-getIdentityAssertion] + 6. If the identity request was triggered by a createOffer() or createAnswer(), + then the assertion is converted to a JSON string, base64-encoded and inserted + into an a=identity attribute in the session description. + + [RTCPeerConnection-getIdentityAssertion] + If assertion generation fails, then the promise for the corresponding function call + is rejected with a newly created OperationError. + +9.3.1 User Login Procedure + [RTCPeerConnection-getIdentityAssertion] + An IdP MAY reject an attempt to generate an identity assertion if it is unable to + verify that a user is authenticated. This might be due to the IdP not having the + necessary authentication information available to it (such as cookies). + + [RTCPeerConnection-getIdentityAssertion] + Rejecting the promise returned by generateAssertion will cause the error to propagate + to the application. Login errors are indicated by rejecting the promise with an RTCError + with errorDetail set to "idp-need-login". + + [RTCPeerConnection-getIdentityAssertion] + The URL to login at will be passed to the application in the idpLoginUrl attribute of + the RTCPeerConnection. + + [Out of Scope] + An application can load the login URL in an IFRAME or popup window; the resulting page + then SHOULD provide the user with an opportunity to enter any information necessary to + complete the authorization process. + + [Out of Scope] + Once the authorization process is complete, the page loaded in the IFRAME or popup sends + a message using postMessage [webmessaging] to the page that loaded it (through the + window.opener attribute for popups, or through window.parent for pages loaded in an IFRAME). + The message MUST consist of the DOMString "LOGINDONE". This message informs the application + that another attempt at generating an identity assertion is likely to be successful. + +9.4. Verifying Identity Assertions + The identity assertion request process involves the following asynchronous steps: + + [TODO] + 1. The RTCPeerConnection awaits any prior identity validation. Only one identity + validation can run at a time for an RTCPeerConnection. This can happen because + the resolution of setRemoteDescription is not blocked by identity validation + unless there is a target peer identity. + + [RTCPeerConnection-peerIdentity] + 2. The RTCPeerConnection loads the identity assertion from the session description + and decodes the base64 value, then parses the resulting JSON. The idp parameter + of the resulting dictionary contains a domain and an optional protocol value + that identifies the IdP, as described in [RTCWEB-SECURITY-ARCH]. + + [RTCPeerConnection-peerIdentity] + 3. The RTCPeerConnection instantiates the identified IdP as described in 9.1.1 + Identity Provider Selection and 9.2 Registering an IdP Proxy. If the IdP + cannot be loaded, instantiated or the IdP proxy is not registered, this + process fails. + + [RTCPeerConnection-peerIdentity] + 4. The RTCPeerConnection invokes the validateAssertion method registered by the IdP. + + [RTCPeerConnection-peerIdentity] + The assertion parameter is taken from the decoded identity assertion. The origin + parameter contains the origin of the script that calls the RTCPeerConnection + method that triggers this behavior. + + [RTCPeerConnection-peerIdentity] + 5. The IdP proxy returns a promise and performs the validation process asynchronously. + + [Out of Scope] + The IdP proxy verifies the identity assertion using whatever means necessary. + Depending on the authentication protocol this could involve interacting with the + IdP server. + + [RTCPeerConnection-peerIdentity] + 6. If the IdP proxy produces an error or returns a promise that does not resolve + to a valid RTCIdentityValidationResult (see 9.5 IdP Error Handling), then + identity validation fails. + + [RTCPeerConnection-peerIdentity] + 7. Once the assertion is successfully verified, the IdP proxy resolves the promise + with an RTCIdentityValidationResult containing the validated identity and the + original contents that are the payload of the assertion. + + [RTCPeerConnection-peerIdentity] + 8. The RTCPeerConnection decodes the contents and validates that it contains a + fingerprint value for every a=fingerprint attribute in the session description. + This ensures that the certificate used by the remote peer for communications + is covered by the identity assertion. + + [RTCPeerConnection-peerIdentity] + 9. The RTCPeerConnection validates that the domain portion of the identity matches + the domain of the IdP as described in [RTCWEB-SECURITY-ARCH]. If this check fails + then the identity validation fails. + + [RTCPeerConnection-peerIdentity] + 10. The RTCPeerConnection resolves the peerIdentity attribute with a new instance + of RTCIdentityAssertion that includes the IdP domain and peer identity. + + [Out of Scope] + 11. The user agent MAY display identity information to a user in its UI. Any user + identity information that is displayed in this fashion MUST use a mechanism that + cannot be spoofed by content. + + [RTCPeerConnection-peerIdentity] + If identity validation fails, the peerIdentity promise is rejected with a newly + created OperationError. + + [RTCPeerConnection-peerIdentity] + If identity validation fails and there is a target peer identity for the + RTCPeerConnection, the promise returned by setRemoteDescription MUST be rejected + with the same DOMException. + +9.5. IdP Error Handling + [RTCPeerConnection-getIdentityAssertion] + - A RTCPeerConnection might be configured with an identity provider, but loading of + the IdP URI fails. Any procedure that attempts to invoke such an identity provider + and cannot load the URI fails with an RTCError with errorDetail set to + "idp-load-failure" and the httpRequestStatusCode attribute of the error set to the + HTTP status code of the response. + + [Untestable] + - If the IdP loads fails due to the TLS certificate used for the HTTPS connection not + being trusted, it fails with an RTCError with errorDetail set to "idp-tls-failure". + This typically happens when the IdP uses certificate pinning and an intermediary + such as an enterprise firewall has intercepted the TLS connection. + + [RTCPeerConnection-getIdentityAssertion] + - If the script loaded from the identity provider is not valid JavaScript or does not + implement the correct interfaces, it causes an IdP failure with an RTCError with + errorDetail set to "idp-bad-script-failure". + + [TODO] + - An apparently valid identity provider might fail in several ways. + + If the IdP token has expired, then the IdP MUST fail with an RTCError with + errorDetail set to "idp-token-expired". + + If the IdP token is not valid, then the IdP MUST fail with an RTCError with + errorDetail set to "idp-token-invalid". + + [Untestable] + - The user agent SHOULD limit the time that it allows for an IdP to 15 seconds. + This includes both the loading of the IdP proxy and the identity assertion + generation or validation. Failure to do so potentially causes the corresponding + operation to take an indefinite amount of time. This timer can be cancelled when + the IdP proxy produces a response. Expiration of this timer cases an IdP failure + with an RTCError with errorDetail set to "idp-timeout". + + [RTCPeerConnection-getIdentityAssertion] + - If the identity provider requires the user to login, the operation will fail + RTCError with errorDetail set to "idp-need-login" and the idpLoginUrl attribute + of the error set to the URL that can be used to login. + + [RTCPeerConnection-peerIdentity] + - Even when the IdP proxy produces a positive result, the procedure that uses this + information might still fail. Additional validation of a RTCIdentityValidationResult + value is still necessary. The procedure for validation of identity assertions + describes additional steps that are required to successfully validate the output + of the IdP proxy. + + +Coverage Report + + Tested 29 + Not Tested 2 + Untestable 4 + + Total 35 diff --git a/testing/web-platform/tests/webrtc/coverage/set-session-description.txt b/testing/web-platform/tests/webrtc/coverage/set-session-description.txt new file mode 100644 index 0000000000..f2bb422703 --- /dev/null +++ b/testing/web-platform/tests/webrtc/coverage/set-session-description.txt @@ -0,0 +1,240 @@ +Coverage Report is based on the following editor draft: +https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +4.3.1.6 Set the RTCSessionSessionDescription + + [Trivial] + 1. Let p be a new promise. + + [Trivial] + 2. In parallel, start the process to apply description as described in [JSEP] + (section 5.5. and section 5.6.). + + [Trivial] + 1. If the process to apply description fails for any reason, then user agent + MUST queue a task that runs the following steps: + + [Untestable] + 1. If connection's [[IsClosed]] slot is true, then abort these steps. + + [Untestable] + 2. If elements of the SDP were modified, then reject p with a newly created + InvalidModificationError and abort these steps. + + [RTCPeerConnection-setLocalDescription-answer] + [RTCPeerConnection-setRemoteDescription-offer] + [RTCPeerConnection-setRemoteDescription-answer] + 3. If the description's type is invalid for the current signaling state of + connection as described in [JSEP] (section 5.5. and section 5.6.), then + reject p with a newly created InvalidStateError and abort these steps. + + [RTCPeerConnection-setRemoteDescription-offer] + 4. If the content of description is not valid SDP syntax, then reject p + with an RTCError (with errorDetail set to "sdp-syntax-error" and the + sdpLineNumber attribute set to the line number in the SDP where the + syntax error was detected) and abort these steps. + + [Untestable] + 5. If the content of description is invalid, then reject p with a newly + created InvalidAccessError and abort these steps. + + [Untestable] + 6. For all other errors, for example if description cannot be applied at + the media layer, reject p with a newly created OperationError. + + [Trivial] + 2. If description is applied successfully, the user agent MUST queue a task + that runs the following steps: + + [Untestable] + 1. If connection's [[isClosed]] slot is true, then abort these steps. + + [RTCPeerConnection-setLocalDescription] + 2. If description is set as a local description, then run one of the + following steps: + + [RTCPeerConnection-setLocalDescription-offer] + - If description is of type "offer", set connection.pendingLocalDescription + to description and signaling state to have-local-offer. + + [RTCPeerConnection-setLocalDescription-answer] + - If description is of type "answer", then this completes an offer answer + negotiation. + + Set connection's currentLocalDescription to description and + currentRemoteDescription to the value of pendingRemoteDescription. + + Set both pendingRemoteDescription and pendingLocalDescription to null. + Finally set connection's signaling state to stable + + [RTCPeerConnection-setLocalDescription-rollback] + - If description is of type "rollback", then this is a rollback. Set + connection.pendingLocalDescription to null and signaling state to stable. + + [RTCPeerConnection-setLocalDescription-pranswer] + - If description is of type "pranswer", then set + connection.pendingLocalDescription to description and signaling state to + have-local-pranswer. + + [RTCPeerConnection-setRemoteDescription] + 3. Otherwise, if description is set as a remote description, then run one of the + following steps: + + [RTCPeerConnection-setRemoteDescription-offer] + - If description is of type "offer", set connection.pendingRemoteDescription + attribute to description and signaling state to have-remote-offer. + + [RTCPeerConnection-setRemoteDescription-answer] + - If description is of type "answer", then this completes an offer answer + negotiation. + + Set connection's currentRemoteDescription to description and + currentLocalDescription to the value of pendingLocalDescription. + + Set both pendingRemoteDescription and pendingLocalDescription to null. + + Finally setconnection's signaling state to stable + + [RTCPeerConnection-setRemoteDescription-rollback] + - If description is of type "rollback", then this is a rollback. + Set connection.pendingRemoteDescription to null and signaling state to stable. + + [RTCPeerConnection-setRemoteDescription-rollback] + - If description is of type "pranswer", then set + connection.pendingRemoteDescription to description and signaling state + to have-remote-pranswer. + + [RTCPeerConnection-setLocalDescription] + [RTCPeerConnection-setRemoteDescription] + 4. If connection's signaling state changed above, fire a simple event named + signalingstatechange at connection. + + [TODO] + 5. If description is of type "answer", and it initiates the closure of an existing + SCTP association, as defined in [SCTP-SDP], Sections 10.3 and 10.4, set the value + of connection's [[sctpTransport]] internal slot to null. + + [RTCSctpTransport] + 6. If description is of type "answer" or "pranswer", then run the following steps: + + [RTCSctpTransport] + 1. If description initiates the establishment of a new SCTP association, + as defined in [SCTP-SDP], Sections 10.3 and 10.4, set the value of connection's + [[sctpTransport]] internal slot to a newly created RTCSctpTransport. + + [TODO] + 2. If description negotiates the DTLS role of the SCTP transport, and there is an + RTCDataChannel with a null id, then generate an ID according to + [RTCWEB-DATA-PROTOCOL]. + + [Untestable] + If no available ID could be generated, then run the following steps: + + [Untestable] + 1. Let channel be the RTCDataChannel object for which an ID could not be + generated. + + [Untestable] + 2. Set channel's readyState attribute to closed. + + [Untestable] + 3. Fire an event named error with a ResourceInUse exception at channel. + + [Untestable] + 4. Fire a simple event named close at channel. + + [TODO RTCPeerConnection-setDescription-transceiver] + 7. If description is set as a local description, then run the following steps for + each media description in description that is not yet associated with an + RTCRtpTransceiver object: + + [TODO RTCPeerConnection-setDescription-transceiver] + 1. Let transceiver be the RTCRtpTransceiver used to create the media + description. + + [TODO RTCPeerConnection-setDescription-transceiver] + 2. Set transceiver's mid value to the mid of the corresponding media + description. + + [RTCPeerConnection-ontrack] + 8. If description is set as a remote description, then run the following steps + for each media description in description: + + [TODO RTCPeerConnection-setDescription-transceiver] + 1. As described by [JSEP] (section 5.9.), attempt to find an existing + RTCRtpTransceiver object, transceiver, to represent the media description. + + [RTCPeerConnection-ontrack] + 2. If no suitable transceiver is found (transceiver is unset), run the following + steps: + + [RTCPeerConnection-ontrack] + 1. Create an RTCRtpSender, sender, from the media description. + + [RTCPeerConnection-ontrack] + 2. Create an RTCRtpReceiver, receiver, from the media description. + + [RTCPeerConnection-ontrack] + 3. Create an RTCRtpTransceiver with sender, receiver and direction, and let + transceiver be the result. + + [RTCPeerConnection-ontrack] + 3. Set transceiver's mid value to the mid of the corresponding media description. + If the media description has no MID, and transceiver's mid is unset, generate + a random value as described in [JSEP] (section 5.9.). + + [RTCPeerConnection-ontrack] + 4. If the direction of the media description is sendrecv or sendonly, and + transceiver.receiver.track has not yet been fired in a track event, process + the remote track for the media description, given transceiver. + + [TODO RTCPeerConnection-setDescription-transceiver] + 5. If the media description is rejected, and transceiver is not already stopped, + stop the RTCRtpTransceiver transceiver. + + + [TODO RTCPeerConnection-setDescription-transceiver] + 9. If description is of type "rollback", then run the following steps: + + [TODO RTCPeerConnection-setDescription-transceiver] + 1. If the mid value of an RTCRtpTransceiver was set to a non-null value by + the RTCSessionDescription that is being rolled back, set the mid value + of that transceiver to null, as described by [JSEP] (section 4.1.8.2.). + + [TODO RTCPeerConnection-setDescription-transceiver] + 2. If an RTCRtpTransceiver was created by applying the RTCSessionDescription + that is being rolled back, and a track has not been attached to it via + addTrack, remove that transceiver from connection's set of transceivers, + as described by [JSEP] (section 4.1.8.2.). + + [TODO RTCPeerConnection-setDescription-transceiver] + 3. Restore the value of connection's [[SctpTransport]] internal slot to its + value at the last stable signaling state. + + [RTCPeerConnection-onnegotiationneeded] + 10. If connection's signaling state is now stable, update the negotiation-needed + flag. If connection's [[NegotiationNeeded]] slot was true both before and after + this update, queue a task that runs the following steps: + + [Untestable] + 1. If connection's [[IsClosed]] slot is true, abort these steps. + + [RTCPeerConnection-onnegotiationneeded] + 2. If connection's [[NegotiationNeeded]] slot is false, abort these steps. + + [RTCPeerConnection-onnegotiationneeded] + 3. Fire a simple event named negotiationneeded at connection. + + [Trivial] + 11. Resolve p with undefined. + + [Trivial] + 3. Return p. + + +Coverage Report + + Tested 35 + Not Tested 15 + Untestable 8 + Total 58 diff --git a/testing/web-platform/tests/webrtc/dictionary-helper.js b/testing/web-platform/tests/webrtc/dictionary-helper.js new file mode 100644 index 0000000000..dab7e49fad --- /dev/null +++ b/testing/web-platform/tests/webrtc/dictionary-helper.js @@ -0,0 +1,101 @@ +'use strict'; + +// Helper assertion functions to validate dictionary fields +// on dictionary objects returned from APIs + +function assert_unsigned_int_field(object, field) { + const num = object[field]; + assert_true(Number.isInteger(num) && (num >= 0), + `Expect dictionary.${field} to be unsigned integer`); +} + +function assert_int_field(object, field) { + const num = object[field]; + assert_true(Number.isInteger(num), + `Expect dictionary.${field} to be integer`); +} + +function assert_string_field(object, field) { + const str = object[field]; + assert_equals(typeof str, 'string', + `Expect dictionary.${field} to be string`); +} + +function assert_number_field(object, field) { + const num = object[field]; + assert_equals(typeof num, 'number', + `Expect dictionary.${field} to be number`); +} + +function assert_boolean_field(object, field) { + const bool = object[field]; + assert_equals(typeof bool, 'boolean', + `Expect dictionary.${field} to be boolean`); +} + +function assert_array_field(object, field) { + assert_true(Array.isArray(object[field]), + `Expect dictionary.${field} to be array`); +} + +function assert_dict_field(object, field) { + assert_equals(typeof object[field], 'object', + `Expect dictionary.${field} to be plain object`); + + assert_not_equals(object[field], null, + `Expect dictionary.${field} to not be null`); +} + +function assert_enum_field(object, field, validValues) { + assert_string_field(object, field); + assert_true(validValues.includes(object[field]), + `Expect dictionary.${field} to have one of the valid enum values: ${validValues}`); +} + +function assert_optional_unsigned_int_field(object, field) { + if(object[field] !== undefined) { + assert_unsigned_int_field(object, field); + } +} + +function assert_optional_int_field(object, field) { + if(object[field] !== undefined) { + assert_int_field(object, field); + } +} + +function assert_optional_string_field(object, field) { + if(object[field] !== undefined) { + assert_string_field(object, field); + } +} + +function assert_optional_number_field(object, field) { + if(object[field] !== undefined) { + assert_number_field(object, field); + } +} + +function assert_optional_boolean_field(object, field) { + if(object[field] !== undefined) { + assert_boolean_field(object, field); + } +} + +function assert_optional_array_field(object, field) { + if(object[field] !== undefined) { + assert_array_field(object, field); + } +} + +function assert_optional_dict_field(object, field) { + if(object[field] !== undefined) { + assert_dict_field(object, field); + } +} + +function assert_optional_enum_field(object, field, validValues) { + if(object[field] !== undefined) { + assert_enum_field(object, field, validValues); + } +} diff --git a/testing/web-platform/tests/webrtc/getstats.html b/testing/web-platform/tests/webrtc/getstats.html new file mode 100644 index 0000000000..d6a692bb78 --- /dev/null +++ b/testing/web-platform/tests/webrtc/getstats.html @@ -0,0 +1,130 @@ + + + + + + + RTCPeerConnection GetStats + + +
+

Retrieved stats info

+
+  
+  
+
+
+ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/historical.html b/testing/web-platform/tests/webrtc/historical.html new file mode 100644 index 0000000000..ae7a29dec0 --- /dev/null +++ b/testing/web-platform/tests/webrtc/historical.html @@ -0,0 +1,51 @@ + +Historical WebRTC features + + +
+ diff --git a/testing/web-platform/tests/webrtc/idlharness.https.window.js b/testing/web-platform/tests/webrtc/idlharness.https.window.js new file mode 100644 index 0000000000..98685f1cd1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/idlharness.https.window.js @@ -0,0 +1,146 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: script=./RTCPeerConnection-helper.js +// META: timeout=long + +'use strict'; + +// The following helper functions are called from RTCPeerConnection-helper.js: +// generateAnswer() +// getNoiseStream() + +// Put the global IDL test objects under a parent object. +// This allows easier search for the test cases when +// viewing the web page +const idlTestObjects = {}; + +// Helper function to create RTCTrackEvent object +function initTrackEvent() { + const pc = new RTCPeerConnection(); + const transceiver = pc.addTransceiver('audio'); + const { sender, receiver } = transceiver; + const { track } = receiver; + return new RTCTrackEvent('track', { + receiver, track, transceiver + }); +} + +// List of async test driver functions +const asyncInitTasks = [ + asyncInitCertificate, + asyncInitTransports, + asyncInitMediaStreamTrack, +]; + +// Asynchronously generate an RTCCertificate +function asyncInitCertificate() { + return RTCPeerConnection.generateCertificate({ + name: 'RSASSA-PKCS1-v1_5', + modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + hash: 'SHA-256' + }).then(cert => { + idlTestObjects.certificate = cert; + }); +} + +// Asynchronously generate instances of +// RTCSctpTransport, RTCDtlsTransport, +// and RTCIceTransport +function asyncInitTransports() { + const pc = new RTCPeerConnection(); + pc.createDataChannel('test'); + + // setting answer description initializes pc.sctp + return pc.createOffer() + .then(offer => + pc.setLocalDescription(offer) + .then(() => generateAnswer(offer))) + .then(answer => pc.setRemoteDescription(answer)) + .then(() => { + const sctpTransport = pc.sctp; + assert_true(sctpTransport instanceof RTCSctpTransport, + 'Expect pc.sctp to be instance of RTCSctpTransport'); + idlTestObjects.sctpTransport = sctpTransport; + + const dtlsTransport = sctpTransport.transport; + assert_true(dtlsTransport instanceof RTCDtlsTransport, + 'Expect sctpTransport.transport to be instance of RTCDtlsTransport'); + idlTestObjects.dtlsTransport = dtlsTransport; + + const iceTransport = dtlsTransport.iceTransport; + assert_true(iceTransport instanceof RTCIceTransport, + 'Expect sctpTransport.transport to be instance of RTCDtlsTransport'); + idlTestObjects.iceTransport = iceTransport; + }); +} + +// Asynchoronously generate MediaStreamTrack from getUserMedia +function asyncInitMediaStreamTrack() { + return getNoiseStream({ audio: true }) + .then(mediaStream => { + idlTestObjects.mediaStreamTrack = mediaStream.getTracks()[0]; + }); +} + +// Run all async test drivers, report and swallow any error +// thrown/rejected. Proper test for correct initialization +// of the objects are done in their respective test files. +function asyncInit() { + return Promise.all(asyncInitTasks.map( + task => { + const t = async_test(`Test driver for ${task.name}`); + let promise; + t.step(() => { + promise = task().then( + t.step_func_done(), + t.step_func(err => + assert_unreached(`Failed to run ${task.name}: ${err}`))); + }); + return promise; + })); +} + +idl_test( + ['webrtc'], + ['webidl', 'mediacapture-streams', 'hr-time', 'dom', 'html'], + async idlArray => { + idlArray.add_objects({ + RTCPeerConnection: [`new RTCPeerConnection()`], + RTCSessionDescription: [`new RTCSessionDescription({ type: 'offer' })`], + RTCIceCandidate: [`new RTCIceCandidate({ sdpMid: 1 })`], + RTCDataChannel: [`new RTCPeerConnection().createDataChannel('')`], + RTCRtpTransceiver: [`new RTCPeerConnection().addTransceiver('audio')`], + RTCRtpSender: [`new RTCPeerConnection().addTransceiver('audio').sender`], + RTCRtpReceiver: [`new RTCPeerConnection().addTransceiver('audio').receiver`], + RTCPeerConnectionIceEvent: [`new RTCPeerConnectionIceEvent('ice')`], + RTCPeerConnectionIceErrorEvent: [ + `new RTCPeerConnectionIceErrorEvent('ice-error', { port: 0, errorCode: 701 });` + ], + RTCTrackEvent: [`initTrackEvent()`], + RTCErrorEvent: [`new RTCErrorEvent('error')`], + RTCDataChannelEvent: [ + `new RTCDataChannelEvent('channel', { + channel: new RTCPeerConnection().createDataChannel('') + })` + ], + // Async initialized objects below + RTCCertificate: ['idlTestObjects.certificate'], + RTCSctpTransport: ['idlTestObjects.sctpTransport'], + RTCDtlsTransport: ['idlTestObjects.dtlsTransport'], + RTCIceTransport: ['idlTestObjects.iceTransport'], + MediaStreamTrack: ['idlTestObjects.mediaStreamTrack'], + }); + /* + TODO + RTCRtpContributingSource + RTCRtpSynchronizationSource + RTCDTMFSender + RTCDTMFToneChangeEvent + RTCIdentityProviderRegistrar + RTCIdentityAssertion + */ + + await asyncInit(); + } +); 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 @@ + + +Test legacy offerToReceiveAudio/Video options + + + + + 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 @@ + + +RTCRtpTransceiver with OfferToReceive legacy options + + + + + + + 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 @@ + + +onaddstream tests + + + + + + diff --git a/testing/web-platform/tests/webrtc/no-media-call.html b/testing/web-platform/tests/webrtc/no-media-call.html new file mode 100644 index 0000000000..dba0b1d2df --- /dev/null +++ b/testing/web-platform/tests/webrtc/no-media-call.html @@ -0,0 +1,100 @@ + + + + + + RTCPeerConnection No-Media Connection Test + + +
+

iceConnectionState info

+
+
+ + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/promises-call.html b/testing/web-platform/tests/webrtc/promises-call.html new file mode 100644 index 0000000000..ee64b463ee --- /dev/null +++ b/testing/web-platform/tests/webrtc/promises-call.html @@ -0,0 +1,113 @@ + + + + + + + RTCPeerConnection Data-Only Connection Test with Promises + + +
+

iceConnectionState info

+
+
+ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/README.txt b/testing/web-platform/tests/webrtc/protocol/README.txt new file mode 100644 index 0000000000..5e17fbf9c3 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/README.txt @@ -0,0 +1,22 @@ +This directory contains files that test for behavior relevant to webrtc, +but which is specified in protocol specifications from the IETF, not in +API recommendations from the W3C. + +The main specifications are given in the following RFCs: + +- RFC 7742, "WebRTC Video Processing and Codec Requirements" +- RFC 7874, "WebRTC Audio Codec and Processing Requirements" +- RFC 8825 (draft-ietf-rtcweb-overview) +- RFC 8826 (draft-ietf-rtcweb-security) +- RFC 8827 (draft-ietf-rtcweb-security-arch) +- RFC 8828 (draft-ietf-rtcweb-ip-handling) +- RFC 8829 (draft-ietf-rtcweb-jsep) +- RFC 8831 (draft-ietf-rtcweb-data-channel) +- RFC 8832 (draft-ietf-rtcweb-data-protocol) +- RFC 8834 (draft-ietf-rtcweb-rtp-usage) +- RFC 8835 (draft-ietf-rtcweb-transports) +- RFC 8851 (draft-ietf-mmusic-rid) +- RFC 8853 (draft-ietf-mmusic-sdp-simulcast) +- RFC 8854 (draft-ietf-rtcweb-fec) + +This list is incomplete. diff --git a/testing/web-platform/tests/webrtc/protocol/RTCPeerConnection-payloadTypes.html b/testing/web-platform/tests/webrtc/protocol/RTCPeerConnection-payloadTypes.html new file mode 100644 index 0000000000..066fc2e085 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/RTCPeerConnection-payloadTypes.html @@ -0,0 +1,49 @@ + + + +RTCPeerConnection RTP payload types + + + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/bundle.https.html b/testing/web-platform/tests/webrtc/protocol/bundle.https.html new file mode 100644 index 0000000000..3d2b835baf --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/bundle.https.html @@ -0,0 +1,150 @@ + + + +RTCPeerConnection BUNDLE + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/candidate-exchange.https.html b/testing/web-platform/tests/webrtc/protocol/candidate-exchange.https.html new file mode 100644 index 0000000000..c54f26e6d8 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/candidate-exchange.https.html @@ -0,0 +1,218 @@ + + + +Candidate exchange + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/crypto-suite.https.html b/testing/web-platform/tests/webrtc/protocol/crypto-suite.https.html new file mode 100644 index 0000000000..f13f221b88 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/crypto-suite.https.html @@ -0,0 +1,85 @@ + + +RTCPeerConnection.prototype.createOffer + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/dtls-certificates.html b/testing/web-platform/tests/webrtc/protocol/dtls-certificates.html new file mode 100644 index 0000000000..bc4794cbc1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/dtls-certificates.html @@ -0,0 +1,42 @@ + + + +RTCPeerConnection DTLS certifcate interop + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/dtls-fingerprint-validation.html b/testing/web-platform/tests/webrtc/protocol/dtls-fingerprint-validation.html new file mode 100644 index 0000000000..0ddc8488ae --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/dtls-fingerprint-validation.html @@ -0,0 +1,37 @@ + + + +DTLS fingerprint validation + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/dtls-setup.https.html b/testing/web-platform/tests/webrtc/protocol/dtls-setup.https.html new file mode 100644 index 0000000000..892e6db413 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/dtls-setup.https.html @@ -0,0 +1,135 @@ + + +RTCPeerConnection a=setup SDP parameter test + + + diff --git a/testing/web-platform/tests/webrtc/protocol/h264-profile-levels.https.html b/testing/web-platform/tests/webrtc/protocol/h264-profile-levels.https.html new file mode 100644 index 0000000000..cb0b581c30 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/h264-profile-levels.https.html @@ -0,0 +1,115 @@ + + +RTCPeerConnection H.264 profile levels + + + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/handover-datachannel.html b/testing/web-platform/tests/webrtc/protocol/handover-datachannel.html new file mode 100644 index 0000000000..8f224f822a --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/handover-datachannel.html @@ -0,0 +1,61 @@ + + +RTCPeerConnection Handovers + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/handover.html b/testing/web-platform/tests/webrtc/protocol/handover.html new file mode 100644 index 0000000000..748cbeff8d --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/handover.html @@ -0,0 +1,72 @@ + + +RTCPeerConnection Handovers + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/ice-state.https.html b/testing/web-platform/tests/webrtc/protocol/ice-state.https.html new file mode 100644 index 0000000000..becce59509 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/ice-state.https.html @@ -0,0 +1,130 @@ + + + +RTCPeerConnection Failed State + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/ice-ufragpwd.html b/testing/web-platform/tests/webrtc/protocol/ice-ufragpwd.html new file mode 100644 index 0000000000..bd151284cb --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/ice-ufragpwd.html @@ -0,0 +1,55 @@ + + + +RTCPeerConnection Failed State + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/jsep-initial-offer.https.html b/testing/web-platform/tests/webrtc/protocol/jsep-initial-offer.https.html new file mode 100644 index 0000000000..50527f88df --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/jsep-initial-offer.https.html @@ -0,0 +1,41 @@ + + +RTCPeerConnection.prototype.createOffer + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/missing-fields.html b/testing/web-platform/tests/webrtc/protocol/missing-fields.html new file mode 100644 index 0000000000..d5aafd230e --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/missing-fields.html @@ -0,0 +1,47 @@ + + +RTCPeerconnection SDP parse tests + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/msid-generate.html b/testing/web-platform/tests/webrtc/protocol/msid-generate.html new file mode 100644 index 0000000000..29226c704e --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/msid-generate.html @@ -0,0 +1,160 @@ + + +RTCPeerconnection MSID generation + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/msid-parse.html b/testing/web-platform/tests/webrtc/protocol/msid-parse.html new file mode 100644 index 0000000000..5596446e00 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/msid-parse.html @@ -0,0 +1,83 @@ + + +RTCPeerconnection MSID parsing + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtp-clockrate.html b/testing/web-platform/tests/webrtc/protocol/rtp-clockrate.html new file mode 100644 index 0000000000..4177420050 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtp-clockrate.html @@ -0,0 +1,40 @@ + + + + +RTP clockrate + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtp-demuxing.html b/testing/web-platform/tests/webrtc/protocol/rtp-demuxing.html new file mode 100644 index 0000000000..de08b2197f --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtp-demuxing.html @@ -0,0 +1,109 @@ + + + +RTCPeerConnection payload type demuxing + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtp-extension-support.html b/testing/web-platform/tests/webrtc/protocol/rtp-extension-support.html new file mode 100644 index 0000000000..045701c171 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtp-extension-support.html @@ -0,0 +1,78 @@ + + +RTCPeerConnection RTP extensions + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtp-headerextensions.html b/testing/web-platform/tests/webrtc/protocol/rtp-headerextensions.html new file mode 100644 index 0000000000..c377a613f6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtp-headerextensions.html @@ -0,0 +1,101 @@ + + +payload type handling (assuming rtcp-mux) + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtp-payloadtypes.html b/testing/web-platform/tests/webrtc/protocol/rtp-payloadtypes.html new file mode 100644 index 0000000000..af7656d131 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtp-payloadtypes.html @@ -0,0 +1,61 @@ + + +payload type handling (assuming rtcp-mux) + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/rtx-codecs.https.html b/testing/web-platform/tests/webrtc/protocol/rtx-codecs.https.html new file mode 100644 index 0000000000..78519c75cc --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/rtx-codecs.https.html @@ -0,0 +1,153 @@ + + +RTX codec integrity checks + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/sctp-format.html b/testing/web-platform/tests/webrtc/protocol/sctp-format.html new file mode 100644 index 0000000000..207e51d4c3 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/sctp-format.html @@ -0,0 +1,25 @@ + + +RTCPeerconnection SDP SCTP format test + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/sdes-dont-dont-dont.html b/testing/web-platform/tests/webrtc/protocol/sdes-dont-dont-dont.html new file mode 100644 index 0000000000..e938c84c8b --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/sdes-dont-dont-dont.html @@ -0,0 +1,55 @@ + + + +RTCPeerConnection MUST NOT support SDES + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/simulcast-answer.html b/testing/web-platform/tests/webrtc/protocol/simulcast-answer.html new file mode 100644 index 0000000000..5e19bc08ff --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/simulcast-answer.html @@ -0,0 +1,101 @@ + + +RTCPeerConnection Simulcast Answer + + + diff --git a/testing/web-platform/tests/webrtc/protocol/simulcast-offer.html b/testing/web-platform/tests/webrtc/protocol/simulcast-offer.html new file mode 100644 index 0000000000..77ae7f9510 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/simulcast-offer.html @@ -0,0 +1,33 @@ + + +RTCPeerConnection Simulcast Offer + + + diff --git a/testing/web-platform/tests/webrtc/protocol/split.https.html b/testing/web-platform/tests/webrtc/protocol/split.https.html new file mode 100644 index 0000000000..3fc3bda2a5 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/split.https.html @@ -0,0 +1,98 @@ + + +RTCPeerConnection BUNDLE + + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/unknown-mediatypes.html b/testing/web-platform/tests/webrtc/protocol/unknown-mediatypes.html new file mode 100644 index 0000000000..f5176d1c87 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/unknown-mediatypes.html @@ -0,0 +1,34 @@ + + +RTCPeerconnection SDP handling of unknown media types + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/video-codecs.https.html b/testing/web-platform/tests/webrtc/protocol/video-codecs.https.html new file mode 100644 index 0000000000..4ce0618bca --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/video-codecs.https.html @@ -0,0 +1,95 @@ + + +RTCPeerConnection.prototype.createOffer + + + + diff --git a/testing/web-platform/tests/webrtc/protocol/vp8-fmtp.html b/testing/web-platform/tests/webrtc/protocol/vp8-fmtp.html new file mode 100644 index 0000000000..16ea635949 --- /dev/null +++ b/testing/web-platform/tests/webrtc/protocol/vp8-fmtp.html @@ -0,0 +1,44 @@ + + + +RTCPeerConnection Failed State + + + + diff --git a/testing/web-platform/tests/webrtc/receiver-track-live.https.html b/testing/web-platform/tests/webrtc/receiver-track-live.https.html new file mode 100644 index 0000000000..34569297a6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/receiver-track-live.https.html @@ -0,0 +1,72 @@ + + + + + Remote tracks should not get ended except for stop/close + + + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/recvonly-transceiver-can-become-sendrecv.https.html b/testing/web-platform/tests/webrtc/recvonly-transceiver-can-become-sendrecv.https.html new file mode 100644 index 0000000000..30bbec4f9f --- /dev/null +++ b/testing/web-platform/tests/webrtc/recvonly-transceiver-can-become-sendrecv.https.html @@ -0,0 +1,50 @@ + + + + + diff --git a/testing/web-platform/tests/webrtc/resources/RTCCertificate-postMessage-iframe.html b/testing/web-platform/tests/webrtc/resources/RTCCertificate-postMessage-iframe.html new file mode 100644 index 0000000000..9e52ba0c88 --- /dev/null +++ b/testing/web-platform/tests/webrtc/resources/RTCCertificate-postMessage-iframe.html @@ -0,0 +1,9 @@ + + diff --git a/testing/web-platform/tests/webrtc/simplecall-no-ssrcs.https.html b/testing/web-platform/tests/webrtc/simplecall-no-ssrcs.https.html new file mode 100644 index 0000000000..f2e2084623 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simplecall-no-ssrcs.https.html @@ -0,0 +1,118 @@ + + + + + RTCPeerConnection Connection Test + + + +
+
+ + +
+ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simplecall.https.html b/testing/web-platform/tests/webrtc/simplecall.https.html new file mode 100644 index 0000000000..dbf6b9a508 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simplecall.https.html @@ -0,0 +1,109 @@ + + + + + RTCPeerConnection Connection Test + + + +
+
+ + +
+ + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/basic.https.html b/testing/web-platform/tests/webrtc/simulcast/basic.https.html new file mode 100644 index 0000000000..f7b9def762 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/basic.https.html @@ -0,0 +1,23 @@ + + +RTCPeerConnection Simulcast Tests + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/getStats.https.html b/testing/web-platform/tests/webrtc/simulcast/getStats.https.html new file mode 100644 index 0000000000..b5a9e6eb28 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/getStats.https.html @@ -0,0 +1,34 @@ + + +RTCPeerConnection Simulcast Tests - getStats + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/h264.https.html b/testing/web-platform/tests/webrtc/simulcast/h264.https.html new file mode 100644 index 0000000000..038449aa6e --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/h264.https.html @@ -0,0 +1,31 @@ + + +RTCPeerConnection Simulcast Tests + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/negotiation-encodings.https.html b/testing/web-platform/tests/webrtc/simulcast/negotiation-encodings.https.html new file mode 100644 index 0000000000..c16e2674b0 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/negotiation-encodings.https.html @@ -0,0 +1,534 @@ + + +RTCPeerConnection Simulcast Tests - negotiation/encodings + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/rid-manipulation.html b/testing/web-platform/tests/webrtc/simulcast/rid-manipulation.html new file mode 100644 index 0000000000..a88506305a --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/rid-manipulation.html @@ -0,0 +1,39 @@ + + +RTCPeerConnection Simulcast Tests - RID manipulation + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/setParameters-active.https.html b/testing/web-platform/tests/webrtc/simulcast/setParameters-active.https.html new file mode 100644 index 0000000000..dbe162c610 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/setParameters-active.https.html @@ -0,0 +1,104 @@ + + +RTCPeerConnection Simulcast Tests - setParameters/active + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/setParameters-encodings.https.html b/testing/web-platform/tests/webrtc/simulcast/setParameters-encodings.https.html new file mode 100644 index 0000000000..ac04ca55fb --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/setParameters-encodings.https.html @@ -0,0 +1,462 @@ + + +RTCPeerConnection Simulcast Tests - setParameters/encodings + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/simulcast.js b/testing/web-platform/tests/webrtc/simulcast/simulcast.js new file mode 100644 index 0000000000..4682729233 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/simulcast.js @@ -0,0 +1,254 @@ +'use strict'; +/* Helper functions to munge SDP and split the sending track into + * separate tracks on the receiving end. This can be done in a number + * of ways, the one used here uses the fact that the MID and RID header + * extensions which are used for packet routing share the same wire + * format. The receiver interprets the rids from the sender as mids + * which allows receiving the different spatial resolutions on separate + * m-lines and tracks. + */ + +const ridExtensions = [ + "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", + "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id", +]; + +function ridToMid(description, rids) { + const sections = SDPUtils.splitSections(description.sdp); + const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); + const ice = SDPUtils.getIceParameters(sections[1], sections[0]); + const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); + const setupValue = description.sdp.match(/a=setup:(.*)/)[1]; + const directionValue = + sections[1].match(/a=sendrecv|a=sendonly|a=recvonly|a=inactive/)[0]; + const mline = SDPUtils.parseMLine(sections[1]); + + // Skip mid extension; we are replacing it with the rid extmap + rtpParameters.headerExtensions = rtpParameters.headerExtensions.filter( + ext => ext.uri != "urn:ietf:params:rtp-hdrext:sdes:mid" + ); + + for (const ext of rtpParameters.headerExtensions) { + if (ext.uri == "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id") { + ext.uri = "urn:ietf:params:rtp-hdrext:sdes:mid"; + } + } + + // Filter rtx as we have no way to (re)interpret rrid. + // Not doing this makes probing use RTX, it's not understood and ramp-up is slower. + rtpParameters.codecs = rtpParameters.codecs.filter(c => c.name.toUpperCase() !== 'RTX'); + + if (!rids) { + rids = Array.from(description.sdp.matchAll(/a=rid:(.*) send/g)).map(r => r[1]); + } + + let sdp = SDPUtils.writeSessionBoilerplate() + + SDPUtils.writeDtlsParameters(dtls, setupValue) + + SDPUtils.writeIceParameters(ice) + + 'a=group:BUNDLE ' + rids.join(' ') + '\r\n'; + const baseRtpDescription = SDPUtils.writeRtpDescription(mline.kind, rtpParameters); + for (const rid of rids) { + sdp += baseRtpDescription + + 'a=mid:' + rid + '\r\n' + + 'a=msid:rid-' + rid + ' rid-' + rid + '\r\n'; + sdp += directionValue + "\r\n"; + } + return sdp; +} + +function midToRid(description, localDescription, rids) { + const sections = SDPUtils.splitSections(description.sdp); + const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); + const ice = SDPUtils.getIceParameters(sections[1], sections[0]); + const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); + const setupValue = description.sdp.match(/a=setup:(.*)/)[1]; + const directionValue = + sections[1].match(/a=sendrecv|a=sendonly|a=recvonly|a=inactive/)[0]; + const mline = SDPUtils.parseMLine(sections[1]); + + // Skip rid extensions; we are replacing them with the mid extmap + rtpParameters.headerExtensions = rtpParameters.headerExtensions.filter( + ext => !ridExtensions.includes(ext.uri) + ); + + for (const ext of rtpParameters.headerExtensions) { + if (ext.uri == "urn:ietf:params:rtp-hdrext:sdes:mid") { + ext.uri = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"; + } + } + + const localMid = localDescription ? SDPUtils.getMid(SDPUtils.splitSections(localDescription.sdp)[1]) : "0"; + + if (!rids) { + rids = []; + for (let i = 1; i < sections.length; i++) { + rids.push(SDPUtils.getMid(sections[i])); + } + } + + let sdp = SDPUtils.writeSessionBoilerplate() + + SDPUtils.writeDtlsParameters(dtls, setupValue) + + SDPUtils.writeIceParameters(ice) + + 'a=group:BUNDLE ' + localMid + '\r\n'; + sdp += SDPUtils.writeRtpDescription(mline.kind, rtpParameters); + // Although we are converting mids to rids, we still need a mid. + // The first one will be consistent with trickle ICE candidates. + sdp += 'a=mid:' + localMid + '\r\n'; + sdp += directionValue + "\r\n"; + + for (const rid of rids) { + const stringrid = String(rid); // allow integers + const choices = stringrid.split(","); + choices.forEach(choice => { + sdp += 'a=rid:' + choice + ' recv\r\n'; + }); + } + if (rids.length) { + sdp += 'a=simulcast:recv ' + rids.join(';') + '\r\n'; + } + + return sdp; +} + +async function doOfferToSendSimulcast(offerer, answerer) { + await offerer.setLocalDescription(); + + // Is this a renegotiation? If so, we cannot remove (or reorder!) any mids, + // even if some rids have been removed or reordered. + let mids = []; + if (answerer.localDescription) { + // Renegotiation. Mids must be the same as before, because renegotiation + // can never remove or reorder mids, nor can it expand the simulcast + // envelope. + mids = [...answerer.localDescription.sdp.matchAll(/a=mid:(.*)/g)].map( + e => e[1] + ); + } else { + // First negotiation; the mids will be exactly the same as the rids + const simulcastAttr = offerer.localDescription.sdp.match( + /a=simulcast:send (.*)/ + ); + if (simulcastAttr) { + mids = simulcastAttr[1].split(";"); + } + } + + const nonSimulcastOffer = ridToMid(offerer.localDescription, mids); + await answerer.setRemoteDescription({ + type: "offer", + sdp: nonSimulcastOffer, + }); +} + +async function doAnswerToRecvSimulcast(offerer, answerer, rids) { + await answerer.setLocalDescription(); + const simulcastAnswer = midToRid( + answerer.localDescription, + offerer.localDescription, + rids + ); + await offerer.setRemoteDescription({ type: "answer", sdp: simulcastAnswer }); +} + +async function doOfferToRecvSimulcast(offerer, answerer, rids) { + await offerer.setLocalDescription(); + const simulcastOffer = midToRid( + offerer.localDescription, + answerer.localDescription, + rids + ); + await answerer.setRemoteDescription({ type: "offer", sdp: simulcastOffer }); +} + +async function doAnswerToSendSimulcast(offerer, answerer) { + await answerer.setLocalDescription(); + + // See which mids the offerer had; it will barf if we remove or reorder them + const mids = [...offerer.localDescription.sdp.matchAll(/a=mid:(.*)/g)].map( + e => e[1] + ); + + const nonSimulcastAnswer = ridToMid(answerer.localDescription, mids); + await offerer.setRemoteDescription({ + type: "answer", + sdp: nonSimulcastAnswer, + }); +} + +async function doOfferToSendSimulcastAndAnswer(offerer, answerer, rids) { + await doOfferToSendSimulcast(offerer, answerer); + await doAnswerToRecvSimulcast(offerer, answerer, rids); +} + +async function doOfferToRecvSimulcastAndAnswer(offerer, answerer, rids) { + await doOfferToRecvSimulcast(offerer, answerer, rids); + await doAnswerToSendSimulcast(offerer, answerer); +} + +function swapRidAndMidExtensionsInSimulcastOffer(offer, rids) { + return ridToMid(offer, rids); +} + +function swapRidAndMidExtensionsInSimulcastAnswer(answer, localDescription, rids) { + return midToRid(answer, localDescription, rids); +} + +async function negotiateSimulcastAndWaitForVideo( + t, rids, pc1, pc2, codec, scalabilityMode = undefined) { + exchangeIceCandidates(pc1, pc2); + + const metadataToBeLoaded = []; + pc2.ontrack = (e) => { + const stream = e.streams[0]; + const v = document.createElement('video'); + v.autoplay = true; + v.srcObject = stream; + v.id = stream.id + metadataToBeLoaded.push(new Promise((resolve) => { + v.addEventListener('loadedmetadata', () => { + resolve(); + }); + })); + }; + + const sendEncodings = rids.map(rid => ({rid})); + // Use a 2X downscale factor between each layer. To improve ramp-up time, the + // top layer is scaled down by a factor 2. Smaller layer comes first. For + // example if MediaStreamTrack is 720p and we want to send three layers we'll + // get {90p, 180p, 360p}. + let scaleResolutionDownBy = 2; + for (let i = sendEncodings.length - 1; i >= 0; --i) { + if (scalabilityMode) { + sendEncodings[i].scalabilityMode = scalabilityMode; + } + sendEncodings[i].scaleResolutionDownBy = scaleResolutionDownBy; + scaleResolutionDownBy *= 2; + } + + // Use getUserMedia as getNoiseStream does not have enough entropy to ramp-up. + await setMediaPermission(); + const stream = await navigator.mediaDevices.getUserMedia({video: {width: 1280, height: 720}}); + t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); + const transceiver = pc1.addTransceiver(stream.getVideoTracks()[0], { + streams: [stream], + sendEncodings: sendEncodings, + }); + if (codec) { + preferCodec(transceiver, codec.mimeType, codec.sdpFmtpLine); + } + + const offer = await pc1.createOffer(); + await pc1.setLocalDescription(offer), + await pc2.setRemoteDescription({ + type: 'offer', + sdp: swapRidAndMidExtensionsInSimulcastOffer(offer, rids), + }); + const answer = await pc2.createAnswer(); + await pc2.setLocalDescription(answer); + await pc1.setRemoteDescription({ + type: 'answer', + sdp: swapRidAndMidExtensionsInSimulcastAnswer(answer, pc1.localDescription, rids), + }); + assert_equals(metadataToBeLoaded.length, rids.length); + return Promise.all(metadataToBeLoaded); +} diff --git a/testing/web-platform/tests/webrtc/simulcast/vp8.https.html b/testing/web-platform/tests/webrtc/simulcast/vp8.https.html new file mode 100644 index 0000000000..3d04bc7172 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/vp8.https.html @@ -0,0 +1,26 @@ + + +RTCPeerConnection Simulcast Tests + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/vp9-scalability-mode.https.html b/testing/web-platform/tests/webrtc/simulcast/vp9-scalability-mode.https.html new file mode 100644 index 0000000000..9dc8a3103d --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/vp9-scalability-mode.https.html @@ -0,0 +1,35 @@ + + +RTCPeerConnection Simulcast Tests + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/simulcast/vp9.https.html b/testing/web-platform/tests/webrtc/simulcast/vp9.https.html new file mode 100644 index 0000000000..a033dab477 --- /dev/null +++ b/testing/web-platform/tests/webrtc/simulcast/vp9.https.html @@ -0,0 +1,26 @@ + + +RTCPeerConnection Simulcast Tests + + + + + + + + + + diff --git a/testing/web-platform/tests/webrtc/third_party/README.md b/testing/web-platform/tests/webrtc/third_party/README.md new file mode 100644 index 0000000000..56a2295dd1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/third_party/README.md @@ -0,0 +1,5 @@ +## sdp +Third-party SDP module from + https://www.npmjs.com/package/sdp +without tests or dependencies. See the commit message for version +and commit information diff --git a/testing/web-platform/tests/webrtc/third_party/sdp/LICENSE b/testing/web-platform/tests/webrtc/third_party/sdp/LICENSE new file mode 100644 index 0000000000..09502ec0a1 --- /dev/null +++ b/testing/web-platform/tests/webrtc/third_party/sdp/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 Philipp Hancke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/testing/web-platform/tests/webrtc/third_party/sdp/sdp.js b/testing/web-platform/tests/webrtc/third_party/sdp/sdp.js new file mode 100644 index 0000000000..a7538a671e --- /dev/null +++ b/testing/web-platform/tests/webrtc/third_party/sdp/sdp.js @@ -0,0 +1,825 @@ +/* eslint-env node */ +'use strict'; + +// SDP helpers. +var SDPUtils = {}; + +// Generate an alphanumeric identifier for cname or mids. +// TODO: use UUIDs instead? https://gist.github.com/jed/982883 +SDPUtils.generateIdentifier = function() { + return Math.random().toString(36).substr(2, 10); +}; + +// The RTCP CNAME used by all peerconnections from the same JS. +SDPUtils.localCName = SDPUtils.generateIdentifier(); + +// Splits SDP into lines, dealing with both CRLF and LF. +SDPUtils.splitLines = function(blob) { + return blob.trim().split('\n').map(function(line) { + return line.trim(); + }); +}; +// Splits SDP into sessionpart and mediasections. Ensures CRLF. +SDPUtils.splitSections = function(blob) { + var parts = blob.split('\nm='); + return parts.map(function(part, index) { + return (index > 0 ? 'm=' + part : part).trim() + '\r\n'; + }); +}; + +// returns the session description. +SDPUtils.getDescription = function(blob) { + var sections = SDPUtils.splitSections(blob); + return sections && sections[0]; +}; + +// returns the individual media sections. +SDPUtils.getMediaSections = function(blob) { + var sections = SDPUtils.splitSections(blob); + sections.shift(); + return sections; +}; + +// Returns lines that start with a certain prefix. +SDPUtils.matchPrefix = function(blob, prefix) { + return SDPUtils.splitLines(blob).filter(function(line) { + return line.indexOf(prefix) === 0; + }); +}; + +// Parses an ICE candidate line. Sample input: +// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 +// rport 55996" +SDPUtils.parseCandidate = function(line) { + var parts; + // Parse both variants. + if (line.indexOf('a=candidate:') === 0) { + parts = line.substring(12).split(' '); + } else { + parts = line.substring(10).split(' '); + } + + var candidate = { + foundation: parts[0], + component: parseInt(parts[1], 10), + protocol: parts[2].toLowerCase(), + priority: parseInt(parts[3], 10), + ip: parts[4], + address: parts[4], // address is an alias for ip. + port: parseInt(parts[5], 10), + // skip parts[6] == 'typ' + type: parts[7] + }; + + for (var i = 8; i < parts.length; i += 2) { + switch (parts[i]) { + case 'raddr': + candidate.relatedAddress = parts[i + 1]; + break; + case 'rport': + candidate.relatedPort = parseInt(parts[i + 1], 10); + break; + case 'tcptype': + candidate.tcpType = parts[i + 1]; + break; + case 'ufrag': + candidate.ufrag = parts[i + 1]; // for backward compability. + candidate.usernameFragment = parts[i + 1]; + break; + default: // extension handling, in particular ufrag + candidate[parts[i]] = parts[i + 1]; + break; + } + } + return candidate; +}; + +// Translates a candidate object into SDP candidate attribute. +SDPUtils.writeCandidate = function(candidate) { + var sdp = []; + sdp.push(candidate.foundation); + sdp.push(candidate.component); + sdp.push(candidate.protocol.toUpperCase()); + sdp.push(candidate.priority); + sdp.push(candidate.address || candidate.ip); + sdp.push(candidate.port); + + var type = candidate.type; + sdp.push('typ'); + sdp.push(type); + if (type !== 'host' && candidate.relatedAddress && + candidate.relatedPort) { + sdp.push('raddr'); + sdp.push(candidate.relatedAddress); + sdp.push('rport'); + sdp.push(candidate.relatedPort); + } + if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') { + sdp.push('tcptype'); + sdp.push(candidate.tcpType); + } + if (candidate.usernameFragment || candidate.ufrag) { + sdp.push('ufrag'); + sdp.push(candidate.usernameFragment || candidate.ufrag); + } + return 'candidate:' + sdp.join(' '); +}; + +// Parses an ice-options line, returns an array of option tags. +// a=ice-options:foo bar +SDPUtils.parseIceOptions = function(line) { + return line.substr(14).split(' '); +}; + +// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input: +// a=rtpmap:111 opus/48000/2 +SDPUtils.parseRtpMap = function(line) { + var parts = line.substr(9).split(' '); + var parsed = { + payloadType: parseInt(parts.shift(), 10) // was: id + }; + + parts = parts[0].split('/'); + + parsed.name = parts[0]; + parsed.clockRate = parseInt(parts[1], 10); // was: clockrate + parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1; + // legacy alias, got renamed back to channels in ORTC. + parsed.numChannels = parsed.channels; + return parsed; +}; + +// Generate an a=rtpmap line from RTCRtpCodecCapability or +// RTCRtpCodecParameters. +SDPUtils.writeRtpMap = function(codec) { + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + var channels = codec.channels || codec.numChannels || 1; + return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate + + (channels !== 1 ? '/' + channels : '') + '\r\n'; +}; + +// Parses an a=extmap line (headerextension from RFC 5285). Sample input: +// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset +// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset +SDPUtils.parseExtmap = function(line) { + var parts = line.substr(9).split(' '); + return { + id: parseInt(parts[0], 10), + direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv', + uri: parts[1] + }; +}; + +// Generates a=extmap line from RTCRtpHeaderExtensionParameters or +// RTCRtpHeaderExtension. +SDPUtils.writeExtmap = function(headerExtension) { + return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + + (headerExtension.direction && headerExtension.direction !== 'sendrecv' + ? '/' + headerExtension.direction + : '') + + ' ' + headerExtension.uri + '\r\n'; +}; + +// Parses an ftmp line, returns dictionary. Sample input: +// a=fmtp:96 vbr=on;cng=on +// Also deals with vbr=on; cng=on +SDPUtils.parseFmtp = function(line) { + var parsed = {}; + var kv; + var parts = line.substr(line.indexOf(' ') + 1).split(';'); + for (var j = 0; j < parts.length; j++) { + kv = parts[j].trim().split('='); + parsed[kv[0].trim()] = kv[1]; + } + return parsed; +}; + +// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeFmtp = function(codec) { + var line = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.parameters && Object.keys(codec.parameters).length) { + var params = []; + Object.keys(codec.parameters).forEach(function(param) { + if (codec.parameters[param]) { + params.push(param + '=' + codec.parameters[param]); + } else { + params.push(param); + } + }); + line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n'; + } + return line; +}; + +// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: +// a=rtcp-fb:98 nack rpsi +SDPUtils.parseRtcpFb = function(line) { + var parts = line.substr(line.indexOf(' ') + 1).split(' '); + return { + type: parts.shift(), + parameter: parts.join(' ') + }; +}; +// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeRtcpFb = function(codec) { + var lines = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.rtcpFeedback && codec.rtcpFeedback.length) { + // FIXME: special handling for trr-int? + codec.rtcpFeedback.forEach(function(fb) { + lines += 'a=rtcp-fb:' + pt + ' ' + fb.type + + (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') + + '\r\n'; + }); + } + return lines; +}; + +// Parses an RFC 5576 ssrc media attribute. Sample input: +// a=ssrc:3735928559 cname:something +SDPUtils.parseSsrcMedia = function(line) { + var sp = line.indexOf(' '); + var parts = { + ssrc: parseInt(line.substr(7, sp - 7), 10) + }; + var colon = line.indexOf(':', sp); + if (colon > -1) { + parts.attribute = line.substr(sp + 1, colon - sp - 1); + parts.value = line.substr(colon + 1); + } else { + parts.attribute = line.substr(sp + 1); + } + return parts; +}; + +SDPUtils.parseSsrcGroup = function(line) { + var parts = line.substr(13).split(' '); + return { + semantics: parts.shift(), + ssrcs: parts.map(function(ssrc) { + return parseInt(ssrc, 10); + }) + }; +}; + +// Extracts the MID (RFC 5888) from a media section. +// returns the MID or undefined if no mid line was found. +SDPUtils.getMid = function(mediaSection) { + var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; + if (mid) { + return mid.substr(6); + } +}; + +SDPUtils.parseFingerprint = function(line) { + var parts = line.substr(14).split(' '); + return { + algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge. + value: parts[1] + }; +}; + +// Extracts DTLS parameters from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the fingerprint line as input. See also getIceParameters. +SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=fingerprint:'); + // Note: a=setup line is ignored since we use the 'auto' role. + // Note2: 'algorithm' is not case sensitive except in Edge. + return { + role: 'auto', + fingerprints: lines.map(SDPUtils.parseFingerprint) + }; +}; + +// Serializes DTLS parameters to SDP. +SDPUtils.writeDtlsParameters = function(params, setupType) { + var sdp = 'a=setup:' + setupType + '\r\n'; + params.fingerprints.forEach(function(fp) { + sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'; + }); + return sdp; +}; + +// Parses a=crypto lines into +// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members +SDPUtils.parseCryptoLine = function(line) { + var parts = line.substr(9).split(' '); + return { + tag: parseInt(parts[0], 10), + cryptoSuite: parts[1], + keyParams: parts[2], + sessionParams: parts.slice(3), + }; +}; + +SDPUtils.writeCryptoLine = function(parameters) { + return 'a=crypto:' + parameters.tag + ' ' + + parameters.cryptoSuite + ' ' + + (typeof parameters.keyParams === 'object' + ? SDPUtils.writeCryptoKeyParams(parameters.keyParams) + : parameters.keyParams) + + (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') + + '\r\n'; +}; + +// Parses the crypto key parameters into +// https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam* +SDPUtils.parseCryptoKeyParams = function(keyParams) { + if (keyParams.indexOf('inline:') !== 0) { + return null; + } + var parts = keyParams.substr(7).split('|'); + return { + keyMethod: 'inline', + keySalt: parts[0], + lifeTime: parts[1], + mkiValue: parts[2] ? parts[2].split(':')[0] : undefined, + mkiLength: parts[2] ? parts[2].split(':')[1] : undefined, + }; +}; + +SDPUtils.writeCryptoKeyParams = function(keyParams) { + return keyParams.keyMethod + ':' + + keyParams.keySalt + + (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') + + (keyParams.mkiValue && keyParams.mkiLength + ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength + : ''); +}; + +// Extracts all SDES paramters. +SDPUtils.getCryptoParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=crypto:'); + return lines.map(SDPUtils.parseCryptoLine); +}; + +// Parses ICE information from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the ice-ufrag and ice-pwd lines as input. +SDPUtils.getIceParameters = function(mediaSection, sessionpart) { + var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=ice-ufrag:')[0]; + var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=ice-pwd:')[0]; + if (!(ufrag && pwd)) { + return null; + } + return { + usernameFragment: ufrag.substr(12), + password: pwd.substr(10), + }; +}; + +// Serializes ICE parameters to SDP. +SDPUtils.writeIceParameters = function(params) { + return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + + 'a=ice-pwd:' + params.password + '\r\n'; +}; + +// Parses the SDP media section and returns RTCRtpParameters. +SDPUtils.parseRtpParameters = function(mediaSection) { + var description = { + codecs: [], + headerExtensions: [], + fecMechanisms: [], + rtcp: [] + }; + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..] + var pt = mline[i]; + var rtpmapline = SDPUtils.matchPrefix( + mediaSection, 'a=rtpmap:' + pt + ' ')[0]; + if (rtpmapline) { + var codec = SDPUtils.parseRtpMap(rtpmapline); + var fmtps = SDPUtils.matchPrefix( + mediaSection, 'a=fmtp:' + pt + ' '); + // Only the first a=fmtp: is considered. + codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {}; + codec.rtcpFeedback = SDPUtils.matchPrefix( + mediaSection, 'a=rtcp-fb:' + pt + ' ') + .map(SDPUtils.parseRtcpFb); + description.codecs.push(codec); + // parse FEC mechanisms from rtpmap lines. + switch (codec.name.toUpperCase()) { + case 'RED': + case 'ULPFEC': + description.fecMechanisms.push(codec.name.toUpperCase()); + break; + default: // only RED and ULPFEC are recognized as FEC mechanisms. + break; + } + } + } + SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) { + description.headerExtensions.push(SDPUtils.parseExtmap(line)); + }); + // FIXME: parse rtcp. + return description; +}; + +// Generates parts of the SDP media section describing the capabilities / +// parameters. +SDPUtils.writeRtpDescription = function(kind, caps) { + var sdp = ''; + + // Build the mline. + sdp += 'm=' + kind + ' '; + sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs. + sdp += ' UDP/TLS/RTP/SAVPF '; + sdp += caps.codecs.map(function(codec) { + if (codec.preferredPayloadType !== undefined) { + return codec.preferredPayloadType; + } + return codec.payloadType; + }).join(' ') + '\r\n'; + + sdp += 'c=IN IP4 0.0.0.0\r\n'; + sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'; + + // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. + caps.codecs.forEach(function(codec) { + sdp += SDPUtils.writeRtpMap(codec); + sdp += SDPUtils.writeFmtp(codec); + sdp += SDPUtils.writeRtcpFb(codec); + }); + var maxptime = 0; + caps.codecs.forEach(function(codec) { + if (codec.maxptime > maxptime) { + maxptime = codec.maxptime; + } + }); + if (maxptime > 0) { + sdp += 'a=maxptime:' + maxptime + '\r\n'; + } + sdp += 'a=rtcp-mux\r\n'; + + if (caps.headerExtensions) { + caps.headerExtensions.forEach(function(extension) { + sdp += SDPUtils.writeExtmap(extension); + }); + } + // FIXME: write fecMechanisms. + return sdp; +}; + +// Parses the SDP media section and returns an array of +// RTCRtpEncodingParameters. +SDPUtils.parseRtpEncodingParameters = function(mediaSection) { + var encodingParameters = []; + var description = SDPUtils.parseRtpParameters(mediaSection); + var hasRed = description.fecMechanisms.indexOf('RED') !== -1; + var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; + + // filter a=ssrc:... cname:, ignore PlanB-msid + var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(parts) { + return parts.attribute === 'cname'; + }); + var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; + var secondarySsrc; + + var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID') + .map(function(line) { + var parts = line.substr(17).split(' '); + return parts.map(function(part) { + return parseInt(part, 10); + }); + }); + if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) { + secondarySsrc = flows[0][1]; + } + + description.codecs.forEach(function(codec) { + if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) { + var encParam = { + ssrc: primarySsrc, + codecPayloadType: parseInt(codec.parameters.apt, 10) + }; + if (primarySsrc && secondarySsrc) { + encParam.rtx = {ssrc: secondarySsrc}; + } + encodingParameters.push(encParam); + if (hasRed) { + encParam = JSON.parse(JSON.stringify(encParam)); + encParam.fec = { + ssrc: primarySsrc, + mechanism: hasUlpfec ? 'red+ulpfec' : 'red' + }; + encodingParameters.push(encParam); + } + } + }); + if (encodingParameters.length === 0 && primarySsrc) { + encodingParameters.push({ + ssrc: primarySsrc + }); + } + + // we support both b=AS and b=TIAS but interpret AS as TIAS. + var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b='); + if (bandwidth.length) { + if (bandwidth[0].indexOf('b=TIAS:') === 0) { + bandwidth = parseInt(bandwidth[0].substr(7), 10); + } else if (bandwidth[0].indexOf('b=AS:') === 0) { + // use formula from JSEP to convert b=AS to TIAS value. + bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95 + - (50 * 40 * 8); + } else { + bandwidth = undefined; + } + encodingParameters.forEach(function(params) { + params.maxBitrate = bandwidth; + }); + } + return encodingParameters; +}; + +// parses http://draft.ortc.org/#rtcrtcpparameters* +SDPUtils.parseRtcpParameters = function(mediaSection) { + var rtcpParameters = {}; + + // Gets the first SSRC. Note tha with RTX there might be multiple + // SSRCs. + var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(obj) { + return obj.attribute === 'cname'; + })[0]; + if (remoteSsrc) { + rtcpParameters.cname = remoteSsrc.value; + rtcpParameters.ssrc = remoteSsrc.ssrc; + } + + // Edge uses the compound attribute instead of reducedSize + // compound is !reducedSize + var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); + rtcpParameters.reducedSize = rsize.length > 0; + rtcpParameters.compound = rsize.length === 0; + + // parses the rtcp-mux attrіbute. + // Note that Edge does not support unmuxed RTCP. + var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); + rtcpParameters.mux = mux.length > 0; + + return rtcpParameters; +}; + +// parses either a=msid: or a=ssrc:... msid lines and returns +// the id of the MediaStream and MediaStreamTrack. +SDPUtils.parseMsid = function(mediaSection) { + var parts; + var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:'); + if (spec.length === 1) { + parts = spec[0].substr(7).split(' '); + return {stream: parts[0], track: parts[1]}; + } + var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(msidParts) { + return msidParts.attribute === 'msid'; + }); + if (planB.length > 0) { + parts = planB[0].value.split(' '); + return {stream: parts[0], track: parts[1]}; + } +}; + +// SCTP +// parses draft-ietf-mmusic-sctp-sdp-26 first and falls back +// to draft-ietf-mmusic-sctp-sdp-05 +SDPUtils.parseSctpDescription = function(mediaSection) { + var mline = SDPUtils.parseMLine(mediaSection); + var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:'); + var maxMessageSize; + if (maxSizeLine.length > 0) { + maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10); + } + if (isNaN(maxMessageSize)) { + maxMessageSize = 65536; + } + var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:'); + if (sctpPort.length > 0) { + return { + port: parseInt(sctpPort[0].substr(12), 10), + protocol: mline.fmt, + maxMessageSize: maxMessageSize + }; + } + var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:'); + if (sctpMapLines.length > 0) { + var parts = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:')[0] + .substr(10) + .split(' '); + return { + port: parseInt(parts[0], 10), + protocol: parts[1], + maxMessageSize: maxMessageSize + }; + } +}; + +// SCTP +// outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers +// support by now receiving in this format, unless we originally parsed +// as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line +// protocol of DTLS/SCTP -- without UDP/ or TCP/) +SDPUtils.writeSctpDescription = function(media, sctp) { + var output = []; + if (media.protocol !== 'DTLS/SCTP') { + output = [ + 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\r\n', + 'c=IN IP4 0.0.0.0\r\n', + 'a=sctp-port:' + sctp.port + '\r\n' + ]; + } else { + output = [ + 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\r\n', + 'c=IN IP4 0.0.0.0\r\n', + 'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\r\n' + ]; + } + if (sctp.maxMessageSize !== undefined) { + output.push('a=max-message-size:' + sctp.maxMessageSize + '\r\n'); + } + return output.join(''); +}; + +// Generate a session ID for SDP. +// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1 +// recommends using a cryptographically random +ve 64-bit value +// but right now this should be acceptable and within the right range +SDPUtils.generateSessionId = function() { + return Math.floor((Math.random() * 4294967296) + 1); +}; + +// Write boilder plate for start of SDP +// sessId argument is optional - if not supplied it will +// be generated randomly +// sessVersion is optional and defaults to 2 +// sessUser is optional and defaults to 'thisisadapterortc' +SDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) { + var sessionId; + var version = sessVer !== undefined ? sessVer : 2; + if (sessId) { + sessionId = sessId; + } else { + sessionId = SDPUtils.generateSessionId(); + } + var user = sessUser || 'thisisadapterortc'; + // FIXME: sess-id should be an NTP timestamp. + return 'v=0\r\n' + + 'o=' + user + ' ' + sessionId + ' ' + version + + ' IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n'; +}; + +SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) { + var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps); + + // Map ICE parameters (ufrag, pwd) to SDP. + sdp += SDPUtils.writeIceParameters( + transceiver.iceGatherer.getLocalParameters()); + + // Map DTLS parameters to SDP. + sdp += SDPUtils.writeDtlsParameters( + transceiver.dtlsTransport.getLocalParameters(), + type === 'offer' ? 'actpass' : 'active'); + + sdp += 'a=mid:' + transceiver.mid + '\r\n'; + + if (transceiver.direction) { + sdp += 'a=' + transceiver.direction + '\r\n'; + } else if (transceiver.rtpSender && transceiver.rtpReceiver) { + sdp += 'a=sendrecv\r\n'; + } else if (transceiver.rtpSender) { + sdp += 'a=sendonly\r\n'; + } else if (transceiver.rtpReceiver) { + sdp += 'a=recvonly\r\n'; + } else { + sdp += 'a=inactive\r\n'; + } + + if (transceiver.rtpSender) { + // spec. + var msid = 'msid:' + stream.id + ' ' + + transceiver.rtpSender.track.id + '\r\n'; + sdp += 'a=' + msid; + + // for Chrome. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' ' + msid; + if (transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' ' + msid; + sdp += 'a=ssrc-group:FID ' + + transceiver.sendEncodingParameters[0].ssrc + ' ' + + transceiver.sendEncodingParameters[0].rtx.ssrc + + '\r\n'; + } + } + // FIXME: this should be written by writeRtpDescription. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + } + return sdp; +}; + +// Gets the direction from the mediaSection or the sessionpart. +SDPUtils.getDirection = function(mediaSection, sessionpart) { + // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. + var lines = SDPUtils.splitLines(mediaSection); + for (var i = 0; i < lines.length; i++) { + switch (lines[i]) { + case 'a=sendrecv': + case 'a=sendonly': + case 'a=recvonly': + case 'a=inactive': + return lines[i].substr(2); + default: + // FIXME: What should happen here? + } + } + if (sessionpart) { + return SDPUtils.getDirection(sessionpart); + } + return 'sendrecv'; +}; + +SDPUtils.getKind = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + return mline[0].substr(2); +}; + +SDPUtils.isRejected = function(mediaSection) { + return mediaSection.split(' ', 2)[1] === '0'; +}; + +SDPUtils.parseMLine = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var parts = lines[0].substr(2).split(' '); + return { + kind: parts[0], + port: parseInt(parts[1], 10), + protocol: parts[2], + fmt: parts.slice(3).join(' ') + }; +}; + +SDPUtils.parseOLine = function(mediaSection) { + var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]; + var parts = line.substr(2).split(' '); + return { + username: parts[0], + sessionId: parts[1], + sessionVersion: parseInt(parts[2], 10), + netType: parts[3], + addressType: parts[4], + address: parts[5] + }; +}; + +// a very naive interpretation of a valid SDP. +SDPUtils.isValidSDP = function(blob) { + if (typeof blob !== 'string' || blob.length === 0) { + return false; + } + var lines = SDPUtils.splitLines(blob); + for (var i = 0; i < lines.length; i++) { + if (lines[i].length < 2 || lines[i].charAt(1) !== '=') { + return false; + } + // TODO: check the modifier a bit more. + } + return true; +}; + +// Expose public methods. +if (typeof module === 'object') { + module.exports = SDPUtils; +} diff --git a/testing/web-platform/tests/webrtc/toJSON.html b/testing/web-platform/tests/webrtc/toJSON.html new file mode 100644 index 0000000000..8d71353425 --- /dev/null +++ b/testing/web-platform/tests/webrtc/toJSON.html @@ -0,0 +1,48 @@ + +WebRTC objects toJSON() methods + + + diff --git a/testing/web-platform/tests/webrtc/tools/.eslintrc.js b/testing/web-platform/tests/webrtc/tools/.eslintrc.js new file mode 100644 index 0000000000..321f8e9a25 --- /dev/null +++ b/testing/web-platform/tests/webrtc/tools/.eslintrc.js @@ -0,0 +1,154 @@ +module.exports = { + rules: { + 'no-undef': 1, + 'no-unused-vars': 0 + }, + plugins: [ + 'html' + ], + env: { + browser: true, + es6: true + }, + globals: { + // testharness globals + test: true, + async_test: true, + promise_test: true, + IdlArray: true, + assert_true: true, + assert_false: true, + assert_equals: true, + assert_not_equals: true, + assert_array_equals: true, + assert_in_array: true, + assert_unreached: true, + assert_idl_attribute: true, + assert_own_property: true, + assert_greater_than: true, + assert_less_than: true, + assert_greater_than_equal: true, + assert_less_than_equal: true, + assert_approx_equals: true, + + + // WebRTC globals + RTCPeerConnection: true, + RTCRtpSender: true, + RTCRtpReceiver: true, + RTCRtpTransceiver: true, + RTCIceTransport: true, + RTCDtlsTransport: true, + RTCSctpTransport: true, + RTCDataChannel: true, + RTCCertificate: true, + RTCDTMFSender: true, + RTCError: true, + RTCTrackEvent: true, + RTCPeerConnectionIceEvent: true, + RTCDTMFToneChangeEvent: true, + RTCDataChannelEvent: true, + RTCRtpContributingSource: true, + RTCRtpSynchronizationSource: true, + + // dictionary-helper.js + assert_unsigned_int_field: true, + assert_int_field: true, + assert_string_field: true, + assert_number_field: true, + assert_boolean_field: true, + assert_array_field: true, + assert_dict_field: true, + assert_enum_field: true, + + assert_optional_unsigned_int_field: true, + assert_optional_int_field: true, + assert_optional_string_field: true, + assert_optional_number_field: true, + assert_optional_boolean_field: true, + assert_optional_array_field: true, + assert_optional_dict_field: true, + assert_optional_enum_field: true, + + // identity-helper.sub.js + parseAssertionResult: true, + getIdpDomains: true, + assert_rtcerror_rejection: true, + hostString: true, + + // RTCConfiguration-helper.js + config_test: true, + + // RTCDTMFSender-helper.js + createDtmfSender: true, + test_tone_change_events: true, + getTransceiver: true, + + // RTCPeerConnection-helper.js + countLine: true, + countAudioLine: true, + countVideoLine: true, + countApplicationLine: true, + similarMediaDescriptions: true, + assert_is_session_description: true, + isSimilarSessionDescription: true, + assert_session_desc_equals: true, + assert_session_desc_not_equals: true, + generateOffer: true, + generateAnswer: true, + test_state_change_event: true, + test_never_resolve: true, + exchangeIceCandidates: true, + exchangeOfferAnswer: true, + createDataChannelPair: true, + awaitMessage: true, + blobToArrayBuffer: true, + assert_equals_typed_array: true, + generateMediaStreamTrack: true, + getTrackFromUserMedia: true, + getUserMediaTracksAndStreams: true, + performOffer: true, + Resolver: true, + + // RTCRtpCapabilities-helper.js + validateRtpCapabilities: true, + validateCodecCapability: true, + validateHeaderExtensionCapability: true, + + // RTCRtpParameters-helper.js + validateSenderRtpParameters: true, + validateReceiverRtpParameters: true, + validateRtpParameters: true, + validateEncodingParameters: true, + validateRtcpParameters: true, + validateHeaderExtensionParameters: true, + validateCodecParameters: true, + + // RTCStats-helper.js + validateStatsReport: true, + assert_stats_report_has_stats: true, + findStatsFromReport: true, + getRequiredStats: true, + getStatsById: true, + validateIdField: true, + validateOptionalIdField: true, + validateRtcStats: true, + validateRtpStreamStats: true, + validateCodecStats: true, + validateReceivedRtpStreamStats: true, + validateInboundRtpStreamStats: true, + validateRemoteInboundRtpStreamStats: true, + validateSentRtpStreamStats: true, + validateOutboundRtpStreamStats: true, + validateRemoteOutboundRtpStreamStats: true, + validateContributingSourceStats: true, + validatePeerConnectionStats: true, + validateMediaStreamStats: true, + validateMediaStreamTrackStats: true, + validateDataChannelStats: true, + validateTransportStats: true, + validateIceCandidateStats: true, + validateIceCandidatePairStats: true, + validateCertificateStats: true, + } +} diff --git a/testing/web-platform/tests/webrtc/tools/README.md b/testing/web-platform/tests/webrtc/tools/README.md new file mode 100644 index 0000000000..68bc284fdf --- /dev/null +++ b/testing/web-platform/tests/webrtc/tools/README.md @@ -0,0 +1,14 @@ +WebRTC Tools +============ + +This directory contains a simple Node.js project to aid the development of +WebRTC tests. + +## Lint + +```bash +npm run lint +``` + +Does basic linting of the JavaScript code. Mainly for catching usage of +undefined variables. diff --git a/testing/web-platform/tests/webrtc/tools/codemod-peerconnection-addcleanup b/testing/web-platform/tests/webrtc/tools/codemod-peerconnection-addcleanup new file mode 100644 index 0000000000..920921d2e4 --- /dev/null +++ b/testing/web-platform/tests/webrtc/tools/codemod-peerconnection-addcleanup @@ -0,0 +1,58 @@ +/* a codemod for ensuring RTCPeerConnection is cleaned up in tests. + * For each `new RTCPeerConnection` add a + * `test.add_cleanup(() => pc.close())` + * Only applies in promise_tests if there is no add_cleanup in the + * test function body. + */ +export default function transformer(file, api) { + const j = api.jscodeshift; + return j(file.source) + // find each RTCPeerConnection constructor + .find(j.NewExpression, {callee: {type: 'Identifier', name: 'RTCPeerConnection'}}) + + // check it is inside a promise_test + .filter(path => { + // iterate parentPath until you find a CallExpression + let nextPath = path.parentPath; + while (nextPath && nextPath.value.type !== 'CallExpression') { + nextPath = nextPath.parentPath; + } + return nextPath && nextPath.value.callee.name === 'promise_test'; + }) + // check there is no add_cleanup in the function body + .filter(path => { + let nextPath = path.parentPath; + while (nextPath && nextPath.value.type !== 'CallExpression') { + nextPath = nextPath.parentPath; + } + const body = nextPath.value.arguments[0].body; + return j(body).find(j.Identifier, {name: 'add_cleanup'}).length === 0; + }) + .forEach(path => { + // iterate parentPath until you find a CallExpression + let nextPath = path.parentPath; + while (nextPath && nextPath.value.type !== 'CallExpression') { + nextPath = nextPath.parentPath; + } + const declaration = path.parentPath.parentPath.parentPath; + const pc = path.parentPath.value.id; + + declaration.insertAfter( + j.expressionStatement( + j.callExpression( + j.memberExpression( + nextPath.node.arguments[0].params[0], + j.identifier('add_cleanup') + ), + [j.arrowFunctionExpression([], + j.callExpression( + j.memberExpression(pc, j.identifier('close'), false), + [] + ) + )] + ) + ) + ); + }) + .toSource(); +}; diff --git a/testing/web-platform/tests/webrtc/tools/html-codemod.js b/testing/web-platform/tests/webrtc/tools/html-codemod.js new file mode 100644 index 0000000000..6a31e8c4c6 --- /dev/null +++ b/testing/web-platform/tests/webrtc/tools/html-codemod.js @@ -0,0 +1,34 @@ +/* + * extract script content from a series of html files, run a + * jscodeshift codemod on them and overwrite the original file. + * + * Usage: node html-codemod.js codemod-file list of files to process + */ +const { JSDOM } = require('jsdom'); +const fs = require('fs'); +const {execFileSync} = require('child_process'); + +const codemod = process.argv[2]; +const filenames = process.argv.slice(3); +filenames.forEach((filename) => { + const originalContent = fs.readFileSync(filename, 'utf-8'); + const dom = new JSDOM(originalContent); + const document = dom.window.document; + const scriptTags = document.querySelectorAll('script'); + const lastTag = scriptTags[scriptTags.length - 1]; + const script = lastTag.innerHTML; + if (!script) { + console.log('NO SCRIPT FOUND', filename); + return; + } + const scriptFilename = filename + '.codemod.js'; + const scriptFile = fs.writeFileSync(scriptFilename, script); + // exec jscodeshift + const output = execFileSync('./node_modules/.bin/jscodeshift', ['-t', codemod, scriptFilename]); + console.log(filename, output.toString()); // output jscodeshift output. + // read back file, resubstitute + const newScript = fs.readFileSync(scriptFilename, 'utf-8').toString(); + const modifiedContent = originalContent.split(script).join(newScript); + fs.writeFileSync(filename, modifiedContent); + fs.unlinkSync(scriptFilename); +}); diff --git a/testing/web-platform/tests/webrtc/tools/package.json b/testing/web-platform/tests/webrtc/tools/package.json new file mode 100644 index 0000000000..f26cfcc142 --- /dev/null +++ b/testing/web-platform/tests/webrtc/tools/package.json @@ -0,0 +1,16 @@ +{ + "name": "webrtc-testing-tools", + "version": "1.0.0", + "description": "Tools for WebRTC testing", + "scripts": { + "lint": "eslint -c .eslintrc.js ../*.html ../*.js" + }, + "devDependencies": { + "eslint": "^7.24.0", + "eslint-plugin-html": "^4.0.0", + "jscodeshift": "^0.5.1", + "jsdom": "^16.5.3" + }, + "license": "BSD", + "private": true +} -- cgit v1.2.3