aboutsummaryrefslogtreecommitdiffstats
path: root/tests/wpt/web-platform-tests/webrtc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/wpt/web-platform-tests/webrtc')
-rw-r--r--tests/wpt/web-platform-tests/webrtc/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCCertificate.html5
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html6
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js4
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html39
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html4
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html169
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html228
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html108
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html244
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html (renamed from tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html)27
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html181
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js535
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html1
-rw-r--r--tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html75
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js156
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/README.md14
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/package-lock.json1213
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/package.json14
23 files changed, 2442 insertions, 590 deletions
diff --git a/tests/wpt/web-platform-tests/webrtc/OWNERS b/tests/wpt/web-platform-tests/webrtc/OWNERS
index f2d66bf5c08..378bf87a106 100644
--- a/tests/wpt/web-platform-tests/webrtc/OWNERS
+++ b/tests/wpt/web-platform-tests/webrtc/OWNERS
@@ -1,3 +1,4 @@
+@snuggs
@agouaillard
@alvestrand
@dontcallmedom
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html b/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
index f5eccabf91b..e5f1749eb5b 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
@@ -172,8 +172,9 @@
assert_equals(typeof fingerprint, 'object',
'Expect fingerprint to be an object (dictionary)');
- // Can only do simple test as the allowed values may be extended
- assert_true(/^[a-zA-Z\-]+$/.test(fingerprint.algorithm),
+ // https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml
+ const algorithms = ['md2', 'md5', 'sha-1', 'sha-224', 'sha-256', 'sha-384', 'sha-512'];
+ assert_in_array(fingerprint.algorithm, algorithms,
'Expect fingerprint.algorithm to be string of algorithm identifier');
assert_true(/^([0-9a-f]{2}\:)+[0-9a-f]{2}$/.test(fingerprint.value),
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html b/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
index 7387c5424cd..74e8b4b2ae7 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
@@ -64,7 +64,7 @@
assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
pc.setConfiguration({ iceTransportPolicy: 'relay' });
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'relay');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay');
}, `setConfiguration({ iceTransportPolicy: 'relay' }) with initial iceTransportPolicy all should succeed`);
test(() => {
@@ -72,7 +72,7 @@
assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay');
pc.setConfiguration({ iceTransportPolicy: 'all' });
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'all');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
}, `setConfiguration({ iceTransportPolicy: 'all' }) with initial iceTransportPolicy relay should succeed`);
test(() => {
@@ -81,7 +81,7 @@
// default value for iceTransportPolicy is all
pc.setConfiguration({});
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'all');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
}, `setConfiguration({}) with initial iceTransportPolicy relay should set new value to all`);
config_test(makePc => {
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
index b66c4aedbda..97bb6f93479 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
@@ -76,8 +76,8 @@ function test_tone_change_events(testFunc, toneChanges, desc) {
const now = Date.now();
const duration = now - lastEventTime;
- assert_approx_equals(duration, expectedDuration, 150,
- `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} seconds`);
+ assert_approx_equals(duration, expectedDuration, 250,
+ `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} milliseconds`);
lastEventTime = now;
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html b/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
index 0fd5340006b..80d1bfae46d 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
@@ -76,7 +76,7 @@
testedTransports.add(dtlsTransport);
// End the test if both dtlsTransports are tested.
- if(testedTransports.has(dtlsTransport1) && testedTransports.has(dtslTransport2)) {
+ if(testedTransports.has(dtlsTransport1) && testedTransports.has(dtlsTransport2)) {
t.done();
}
})
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
index ce1c2827aac..97205714f07 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
@@ -80,6 +80,8 @@
*/
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () => pc.addTransceiver('invalid'));
}, 'addTransceiver() with string argument as invalid kind should throw TypeError');
@@ -125,6 +127,7 @@
*/
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
@@ -170,6 +173,7 @@
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
@@ -214,18 +218,24 @@
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
const transceiver = pc.addTransceiver('audio', { direction: 'sendonly' });
assert_equals(transceiver.direction, 'sendonly');
}, `addTransceiver() with direction sendonly should have result transceiver.direction be the same`);
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
const transceiver = pc.addTransceiver('audio', { direction: 'inactive' });
assert_equals(transceiver.direction, 'inactive');
}, `addTransceiver() with direction inactive should have result transceiver.direction be the same`);
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
pc.addTransceiver('audio', { direction: 'invalid' }));
@@ -238,8 +248,9 @@
*/
test(t => {
const pc = new RTCPeerConnection();
- const track = generateMediaStreamTrack('audio');
+ t.add_cleanup(() => pc.close());
+ const track = generateMediaStreamTrack('audio');
const transceiver = pc.addTransceiver(track);
const { sender, receiver } = transceiver;
@@ -276,8 +287,9 @@
test(t => {
const pc = new RTCPeerConnection();
- const track = generateMediaStreamTrack('audio');
+ t.add_cleanup(() => pc.close());
+ const track = generateMediaStreamTrack('audio');
const transceiver1 = pc.addTransceiver(track);
const transceiver2 = pc.addTransceiver(track);
@@ -302,7 +314,6 @@
}, 'addTransceiver(track) multiple times should create multiple transceivers');
-
/*
5.1. addTransceiver
6. Verify that each rid value in sendEncodings is composed only of
@@ -310,8 +321,9 @@
of 16 characters. If one of the RIDs does not meet these requirements,
throw a TypeError.
*/
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
@@ -322,8 +334,9 @@
}));
}, 'addTransceiver() with rid containing invalid non-alphanumeric characters should throw TypeError');
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
@@ -334,8 +347,9 @@
}));
}, 'addTransceiver() with rid longer than 16 characters should throw TypeError');
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
pc.addTransceiver('audio', {
sendEncodings: [{
rid: 'foo'
@@ -353,8 +367,9 @@
Aside from rid , all read-only parameters in the RTCRtpEncodingParameters
dictionaries, such as ssrc, must be left unset, or an error will be thrown.
*/
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -364,8 +379,9 @@
}));
}, `addTransceiver() with readonly ssrc set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -377,8 +393,9 @@
}));
}, `addTransceiver() with readonly rtx set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -390,8 +407,10 @@
}));
}, `addTransceiver() with readonly fec set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
pc.addTransceiver('audio', {
sendEncodings: [{
dtx: 'enabled',
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
index 331eefe458d..e00d9870908 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
@@ -73,7 +73,7 @@ for (const attr in initialState) {
if (!window.pc) {
window.pc = new RTCPeerConnection;
}
- assert_equals(pc[attr], initialState[attr]);
+ assert_equals(window.pc[attr], initialState[attr]);
}, attr + ' initial value');
}
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
index a446280eaaa..35e22f934f0 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
@@ -375,7 +375,7 @@ promise_test(t => {
assert_not_equals(channel1.id, null,
'Expect channel1.id to be assigned');
- assert_greater_than_equals(channel1.id, 0,
+ assert_greater_than_equal(channel1.id, 0,
'Expect channel1.id to be set to valid unsigned short');
assert_less_than(channel1.id, 65535,
@@ -386,7 +386,7 @@ promise_test(t => {
assert_not_equals(channel2.id, null,
'Expect channel2.id to be assigned');
- assert_greater_than_equals(channel2.id, 0,
+ assert_greater_than_equal(channel2.id, 0,
'Expect channel2.id to be set to valid unsigned short');
assert_less_than(channel2.id, 65535,
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html
new file mode 100644
index 00000000000..c599b1c0d07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html
@@ -0,0 +1,169 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test legacy offerToReceiveAudio/Video options</title>
+<link rel="help" href="https://w3c.github.io/webrtc-pc/#legacy-configuration-extensions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+ 'use strict';
+
+ // Run some tests for both audio and video kinds
+ ['audio', 'video'].forEach((kind) => {
+ const capsKind = kind[0].toUpperCase() + kind.slice(1);
+
+ const offerToReceiveTrue = {};
+ offerToReceiveTrue[`offerToReceive${capsKind}`] = true;
+
+ const offerToReceiveFalse = {};
+ offerToReceiveFalse[`offerToReceive${capsKind}`] = false;
+
+ // Start testing
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const dummy = pc.createDataChannel('foo'); // Just to have something to offer
+
+ return pc.createOffer(offerToReceiveFalse)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 0,
+ 'Expect pc to have no transceivers');
+ });
+ }, `createOffer() with offerToReceive${capsKind} set to false should not create a transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer(offerToReceiveTrue)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'recvonly',
+ 'Expect transceiver to have "recvonly" direction');
+ });
+ }, `createOffer() with offerToReceive${capsKind} should create a "recvonly" transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer(offerToReceiveTrue)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'recvonly',
+ 'Expect transceiver to have "recvonly" direction');
+ })
+ .then(() => pc.createOffer(offerToReceiveTrue))
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to still have only one transceiver');
+ })
+ ;
+ }, `offerToReceive${capsKind} option should be ignored if a non-stopped "recvonly" transceiver exists`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer();
+ })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendrecv',
+ 'Expect transceiver to have "sendrecv" direction');
+ })
+ .then(() => pc.createOffer(offerToReceiveTrue))
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to still have only one transceiver');
+ })
+ ;
+ }, `offerToReceive${capsKind} option should be ignored if a non-stopped "sendrecv" transceiver exists`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer(offerToReceiveFalse);
+ })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendonly',
+ 'Expect transceiver to have "sendonly" direction');
+ })
+ ;
+ }, `offerToReceive${capsKind} set to false with a track should create a "sendonly" transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ pc.addTransceiver(kind, {direction: 'recvonly'});
+
+ return pc.createOffer(offerToReceiveFalse)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'inactive',
+ 'Expect transceiver to have "inactive" direction');
+ })
+ ;
+ }, `offerToReceive${capsKind} set to false with a "recvonly" transceiver should change the direction to "inactive"`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer();
+ })
+ .then((offer) => pc.setLocalDescription(offer))
+ .then(() => pc2.setRemoteDescription(pc.localDescription))
+ .then(() => pc2.createAnswer())
+ .then((answer) => pc2.setLocalDescription(answer))
+ .then(() => pc.setRemoteDescription(pc2.localDescription))
+ .then(() => pc.createOffer(offerToReceiveFalse))
+ .then((offer) => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendonly',
+ 'Expect transceiver to have "sendonly" direction');
+ })
+ ;
+ }, `subsequent offerToReceive${capsKind} set to false with a track should change the direction to "sendonly"`);
+ });
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 2,
+ 'Expect pc to have two transceivers');
+
+ assert_equals(pc.getTransceivers()[0].direction, 'recvonly',
+ 'Expect first transceiver to have "recvonly" direction');
+ assert_equals(pc.getTransceivers()[1].direction, 'recvonly',
+ 'Expect second transceiver to have "recvonly" direction');
+ });
+ }, 'offerToReceiveAudio and Video should create two "recvonly" transceivers');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
index a4df5630a3a..73138507d4f 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
@@ -10,8 +10,8 @@
'use strict';
// Test is based on the following editor draft:
- // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
- // https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
+ // webrtc-pc 20171130
+ // webrtc-stats 20171122
// The following helper function is called from RTCPeerConnection-helper.js
// getTrackFromUserMedia
@@ -20,39 +20,25 @@
// validateStatsReport
// assert_stats_report_has_stats
- /*
- 8.2. RTCPeerConnection Interface Extensions
- partial interface RTCPeerConnection {
- Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
- };
-
- 8.3. RTCStatsReport Object
- interface RTCStatsReport {
- readonly maplike<DOMString, object>;
- };
-
- 8.4. RTCStats Dictionary
- dictionary RTCStats {
- DOMHighResTimeStamp timestamp;
- RTCStatsType type;
- DOMString id;
- };
-
- id
- Two RTCStats objects, extracted from two different RTCStatsReport objects, MUST
- have the same id if they were produced by inspecting the same underlying object.
+ // The following helper function is called from RTCPeerConnection-helper.js
+ // exchangeIceCandidates
+ // doSignalingHandshake
+ /*
8.2. getStats
1. Let selectorArg be the method's first argument.
2. Let connection be the RTCPeerConnection object on which the method was invoked.
- 3. If selectorArg is neither null nor a valid MediaStreamTrack, return a promise
- rejected with a newly created TypeError.
+ 3. If selectorArg is null, let selector be null.
+ 4. If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
+ or RTCRtpReceiver on connection which track member matches selectorArg.
+ If no such sender or receiver exists, or if more than one sender or
+ receiver fit this criteria, return a promise rejected with a newly
+ created InvalidAccessError.
5. Let p be a new promise.
6. Run the following steps in parallel:
1. Gather the stats indicated by selector according to the stats selection algorithm.
2. Resolve p with the resulting RTCStatsReport object, containing the gathered stats.
*/
-
promise_test(() => {
const pc = new RTCPeerConnection();
return pc.getStats();
@@ -65,9 +51,11 @@
/*
8.2. getStats
- 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
- member matches selectorArg. If no such sender or receiver exists, return a promise
- rejected with a newly created InvalidAccessError.
+ 4. If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
+ or RTCRtpReceiver on connection which track member matches selectorArg.
+ If no such sender or receiver exists, or if more than one sender or
+ receiver fit this criteria, return a promise rejected with a newly
+ created InvalidAccessError.
*/
promise_test(t => {
const pc = new RTCPeerConnection();
@@ -94,12 +82,6 @@
return pc.getStats(track);
}, 'getStats() with track added via addTransceiver should succeed');
- /*
- 8.2. getStats
- 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
- member matches selectorArg. If more than one sender or receiver fit this criteria,
- return a promise rejected with a newly created InvalidAccessError.
- */
promise_test(t => {
const pc = new RTCPeerConnection();
return getTrackFromUserMedia('audio')
@@ -140,7 +122,35 @@
validateStatsReport(statsReport);
assert_stats_report_has_stats(statsReport, ['peer-connection']);
});
- }, 'getStats() with no argument should return stats report containing peer-connection stats');
+ }, 'getStats() with no argument should return stats report containing peer-connection stats on an empty PC');
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ return getTrackFromUserMedia('audio')
+ .then(([track, mediaStream]) => {
+ pc.addTrack(track, mediaStream);
+ return pc.getStats();
+ })
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['peer-connection']);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ }, 'getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats');
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ return getTrackFromUserMedia('audio')
+ .then(([track, mediaStream]) => {
+ pc.addTrack(track);
+ return pc.getStats();
+ })
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['peer-connection']);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ }, 'getStats() with no argument should return stats for no-stream tracks');
/*
8.5. The stats selection algorithm
@@ -184,4 +194,150 @@
});
}, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats`);
+ /*
+ 8.6 Mandatory To Implement Stats
+ An implementation MUST support generating statistics of the following types
+ when the corresponding objects exist on a PeerConnection, with the attributes
+ that are listed when they are valid for that object.
+ */
+
+ const mandatoryStats = [
+ "codec",
+ "inbound-rtp",
+ "outbound-rtp",
+ "remote-inbound-rtp",
+ "remote-outbound-rtp",
+ "peer-connection",
+ "data-channel",
+ "stream",
+ "track",
+ "transport",
+ "candidate-pair",
+ "local-candidate",
+ "remote-candidate",
+ "certificate"
+ ];
+
+ async_test(t => {
+ const pc1 = new RTCPeerConnection();
+ t.add_cleanup(() => pc1.close());
+ const pc2 = new RTCPeerConnection();
+ t.add_cleanup(() => pc2.close());
+
+ const dataChannel = pc1.createDataChannel('test-channel');
+
+ return navigator.mediaDevices.getUserMedia({
+ audio: true,
+ video: true
+ })
+ .then(t.step_func(mediaStream => {
+ const tracks = mediaStream.getTracks();
+ assert_equals(tracks.length, 2,
+ 'Expect media stream to have one audio and one video track');
+
+ let audioTrack;
+ let videoTrack;
+
+ for (const track of tracks) {
+ t.add_cleanup(() => track.stop());
+
+ pc1.addTrack(track, mediaStream);
+
+ if (track.kind === 'audio') {
+ audioTrack = track;
+ } else if (track.kind === 'video') {
+ videoTrack = track;
+ }
+ }
+
+ if (!audioTrack || ! videoTrack) {
+ assert_unreached('Expect mediaStream to have both audio and video streams');
+ }
+
+ const testStatsReport = (pc, statsReport) => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, mandatoryStats);
+
+ const dataChannelStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'data-channel' &&
+ stats.dataChannelIdentifier === dataChannel.id;
+ },
+ 'Expect data channel stats to be found');
+
+ assert_equals(dataChannelStats.label, 'test-channel');
+
+ const audioTrackStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'track' &&
+ stats.trackIdentifier === audioTrack.id;
+ },
+ 'Expect audio track stats to be found');
+
+ assert_equals(audioTrackStats.kind, 'audio');
+
+ const videoTrackStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'track' &&
+ stats.trackIdentifier === videoTrack.id;
+ },
+ 'Expect video track stats to be found');
+
+ assert_equals(videoTrackStats.kind, 'video');
+
+ const mediaStreamStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'stream' &&
+ stats.streamIdentifier === mediaStream.id;
+ },
+ 'Expect media stream stats to be found');
+
+ assert_true(mediaStreamStats.trackIds.include(audioTrackStats.id));
+ assert_true(mediaStreamStats.trackIds.include(videoTrackStats.id));
+ }
+
+ const onConnected = t.step_func(() => {
+ // Wait a while for the peer connections to collect stats
+ t.step_timeout(() => {
+ Promise.all([
+ pc1.getStats()
+ .then(statsReport => testStatsReport(pc1, statsReport)),
+
+ pc2.getStats()
+ .then(statsReport => testStatsReport(pc2, statsReport))
+ ])
+ .then(t.step_func_done())
+ .catch(t.step_func(err => {
+ assert_unreached(`test failed with error: ${err}`);
+ }));
+ }, 200)
+ })
+
+ let onTrackCount = 0
+ let onDataChannelCalled = false
+
+ pc2.addEventListener('track', t.step_func(() => {
+ onTrackCount++;
+ if (onTrackCount === 2 && onDataChannelCalled) {
+ onConnected();
+ }
+ }));
+
+ pc2.addEventListener('datachannel', t.step_func(() => {
+ onDataChannelCalled = true;
+ if (onTrackCount === 2) {
+ onConnected();
+ }
+ }));
+
+
+ exchangeIceCandidates(pc1, pc2);
+ doSignalingHandshake(pc1, pc2);
+ }))
+ .catch(t.step_func(err => {
+ assert_unreached(`test failed with error: ${err}`);
+ }));
+
+ }, `getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats`);
+
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html
deleted file mode 100644
index 58a153f2946..00000000000
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<meta charset=utf-8>
-<title>IDL check of RTCPeerConnection</title>
-<link rel="author" title="Harald Alvestrand" href="mailto:hta@google.com"/>
-<link rel="help" href="http://w3c.github.io/webrtc-pc/#rtcpeerconnection-interface">
-</head>
-<body>
-
-<h1 class="instructions">Description</h1>
-<p class="instructions">This test verifies the availability of the RTCPeerConnection interface.</p>
-<div id='log'></div>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-
-<!-- The IDL is copied from the 22 September 2015 editors' draft. -->
-<script type="text/plain">
-[Constructor()]
-interface EventTarget {
- // Only a dummy definition is needed here.
-};
-[ Constructor (optional RTCConfiguration configuration)]
-interface RTCPeerConnection : EventTarget {
- Promise<RTCSessionDescription> createOffer (optional RTCOfferOptions options);
- Promise<RTCSessionDescription> createAnswer (optional RTCAnswerOptions options);
- Promise<void> setLocalDescription (RTCSessionDescription description);
- readonly attribute RTCSessionDescription? localDescription;
- readonly attribute RTCSessionDescription? currentLocalDescription;
- readonly attribute RTCSessionDescription? pendingLocalDescription;
- Promise<void> setRemoteDescription (RTCSessionDescription description);
- readonly attribute RTCSessionDescription? remoteDescription;
- readonly attribute RTCSessionDescription? currentRemoteDescription;
- readonly attribute RTCSessionDescription? pendingRemoteDescription;
- Promise<void> addIceCandidate (RTCIceCandidate candidate);
- readonly attribute RTCSignalingState signalingState;
- readonly attribute RTCIceGatheringState iceGatheringState;
- readonly attribute RTCIceConnectionState iceConnectionState;
- readonly attribute boolean? canTrickleIceCandidates;
- RTCConfiguration getConfiguration ();
- void setConfiguration (RTCConfiguration configuration);
- void close ();
- attribute EventHandler onnegotiationneeded;
- attribute EventHandler onicecandidate;
- attribute EventHandler onsignalingstatechange;
- attribute EventHandler oniceconnectionstatechange;
- attribute EventHandler onicegatheringstatechange;
-};
-
-partial interface RTCPeerConnection {
- void createOffer (RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback, optional RTCOfferOptions options);
- void setLocalDescription (RTCSessionDescription description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void createAnswer (RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void setRemoteDescription (RTCSessionDescription description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void addIceCandidate (RTCIceCandidate candidate, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void getStats (MediaStreamTrack? selector, RTCStatsCallback successCallback, RTCPeerConnectionErrorCallback failureCallback);
-};
-
-partial interface RTCPeerConnection {
- static Promise<RTCCertificate> generateCertificate (AlgorithmIdentifier keygenAlgorithm);
-};
-
-partial interface RTCPeerConnection {
- sequence<RTCRtpSender> getSenders ();
- sequence<RTCRtpReceiver> getReceivers ();
- RTCRtpSender addTrack (MediaStreamTrack track, MediaStream... streams);
- void removeTrack (RTCRtpSender sender);
- attribute EventHandler ontrack;
-};
-
-partial interface RTCPeerConnection {
- RTCDataChannel createDataChannel ([TreatNullAs=EmptyString] DOMString label, optional RTCDataChannelInit dataChannelDict);
- attribute EventHandler ondatachannel;
-};
-
-partial interface RTCPeerConnection {
- readonly attribute RTCDTMFSender? dtmf;
-};
-
-partial interface RTCPeerConnection {
- Promise<RTCStatsReport> getStats (optional MediaStreamTrack? selector);
-};
-
-partial interface RTCPeerConnection {
- void setIdentityProvider (DOMString provider, optional DOMString protocol, optional DOMString usernameHint);
- Promise<DOMString> getIdentityAssertion ();
- readonly attribute Promise<RTCIdentityAssertion> peerIdentity;
- readonly attribute DOMString? idpLoginUrl;
-};
-
-</script>
-<script>
-(function() {
- var idl_array = new IdlArray();
- [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"),
- function(node) {
- idl_array.add_idls(node.textContent);
- });
- window.pc = new RTCPeerConnection(null);
- idl_array.add_objects({"RTCPeerConnection": ["pc"]});
- idl_array.test();
- done();
-})();
-</script>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
index 845c55dc6d2..d5f9db9d5d0 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
@@ -284,7 +284,7 @@
pc2.setRemoteDescription(offer))
.then(() =>
assert_rtcerror_rejection('idp-execution-failure',
- peerIdentityPromise,
+ peerIdentityPromise1,
`Expect first peerIdentity promise to be rejected with RTCError('idp-execution-failure')`))
.then(() => {
const peerIdentityPromise2 = pc2.peerIdentity;
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
index f530e94cfe0..d4663e5373b 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
@@ -24,11 +24,11 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
+ const localTrack = tracks[0];
caller.addTrack(localTrack);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- let remoteTrack = trackEvent.track;
+ const remoteTrack = trackEvent.track;
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(trackEvent.streams.length, 0,
@@ -47,15 +47,15 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
- let localStream = streams[0];
+ const localTrack = tracks[0];
+ const localStream = streams[0];
caller.addTrack(localTrack, localStream);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack = trackEvent.track;
- let remoteStream = trackEvent.streams[0];
+ const remoteTrack = trackEvent.track;
+ const remoteStream = trackEvent.streams[0];
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(remoteStream.id, localStream.id,
@@ -74,19 +74,47 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const ontrackResolver = new Resolver();
+ callee.ontrack = () => {
+ eventSequence += 'ontrack;';
+ ontrackResolver.resolve();
+ }
+ caller.addTrack(tracks[0]);
+ return Promise.all([
+ ontrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]);
+ }))
+ .then(t.step_func(() => {
+ assert_equals(eventSequence, 'ontrack;setRemoteDescription;');
+ t.done();
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'ontrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(2)
.then(t.step_func(([tracks, streams]) => {
- let localTrack1 = tracks[0];
- let localTrack2 = tracks[1];
- let localStream = streams[0];
+ const localTrack1 = tracks[0];
+ const localTrack2 = tracks[1];
+ const localStream = streams[0];
caller.addTrack(localTrack1, localStream);
caller.addTrack(localTrack2, localStream);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack1 = trackEvent.track;
- let remoteStream = trackEvent.streams[0];
+ const remoteTrack1 = trackEvent.track;
+ const remoteStream = trackEvent.streams[0];
assert_equals(remoteTrack1.id, localTrack1.id,
'Expected first remote track ID to match first local track ID.');
assert_equals(remoteStream.getTracks().length, 2,
@@ -94,7 +122,7 @@
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack2 = trackEvent.track;
+ const remoteTrack2 = trackEvent.track;
assert_equals(trackEvent.streams[0], remoteStream,
'Expected both track events to fire with the same remote stream.');
assert_equals(remoteTrack2.id, localTrack2.id,
@@ -151,17 +179,53 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(2)
+ .then(t.step_func(([tracks, streams]) => {
+ const localTracks = tracks;
+ const localStream = streams[0];
+ caller.addTrack(localTracks[0], localStream);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ callee.ontrack = null;
+ const remoteStream = trackEvent.streams[0];
+ const onaddtrackResolver = new Resolver();
+ remoteStream.onaddtrack = () => {
+ eventSequence += 'stream.onaddtrack;';
+ onaddtrackResolver.resolve();
+ }
+ caller.addTrack(localTracks[1], localStream);
+ Promise.all([
+ onaddtrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'stream.onaddtrack;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'stream.onaddtrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(2)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
- let localStreams = streams;
+ const localTrack = tracks[0];
+ const localStreams = streams;
caller.addTrack(localTrack, localStreams[0], localStreams[1]);
- let performOffer = performOffer(caller, callee);
+ const performOffer = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 2,
'Expected the track event to fire with two streams.');
- let remoteTrack = trackEvent.track;
- let remoteStreams = trackEvent.streams;
+ const remoteTrack = trackEvent.track;
+ const remoteStreams = trackEvent.streams;
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(remoteStreams[0].id, localStreams[0].id,
@@ -184,38 +248,10 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
- let eventSequence = '';
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
caller.addTrack(tracks[0]);
- let ontrackResolver = new Resolver();
- callee.ontrack = () => {
- eventSequence += 'ontrack;';
- ontrackResolver.resolve();
- }
- return Promise.all([
- ontrackResolver.promise,
- performOffer(caller, callee).then(() => {
- eventSequence += 'setRemoteDescription;';
- })
- ]);
- }))
- .then(t.step_func(() => {
- assert_equals(eventSequence, 'ontrack;setRemoteDescription;');
- t.done();
- }))
- .catch(t.step_func(reason => {
- assert_unreached(reason);
- }));
- }, 'ontrack fires before setRemoteDescription resolves.');
-
- async_test(t => {
- const caller = new RTCPeerConnection();
- const callee = new RTCPeerConnection();
- return getUserMediaTracksAndStreams(1)
- .then(t.step_func(([tracks, streams]) => {
- caller.addTrack(tracks[0]);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_array_equals(callee.getReceivers(), [trackEvent.receiver]);
t.done();
@@ -232,11 +268,11 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- let receivers = callee.getReceivers();
+ const receivers = callee.getReceivers();
assert_equals(receivers.length, 1,
'Expected getReceivers() to be the track event\'s receiver.');
caller.removeTrack(sender);
@@ -259,9 +295,9 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0], streams[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0], streams[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_not_equals(trackEvent.track, null);
assert_equals(trackEvent.streams.length, 1);
@@ -279,21 +315,55 @@
.catch(t.step_func(reason => {
assert_unreached(reason);
}));
- }, 'removeTrack() causes onremovetrack and the track to be removed from the stream.');
+ }, 'removeTrack() makes stream.onremovetrack fire and the track to be removed from the stream.');
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0], streams[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- assert_not_equals(trackEvent.track, null);
+ const remoteStream = trackEvent.streams[0];
+ const onremovetrackResolver = new Resolver();
+ remoteStream.onremovetrack = t.step_func(removeEvent => {
+ eventSequence += 'stream.onremovetrack;';
+ onremovetrackResolver.resolve();
+ });
+ caller.removeTrack(sender);
+ return Promise.all([
+ onremovetrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'stream.onremovetrack;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'stream.onremovetrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ const remoteTrack = trackEvent.track;
caller.removeTrack(sender);
performOffer(caller, callee);
- trackEvent.track.onmute = t.step_func(() => {
+ remoteTrack.onmute = t.step_func(() => {
assert_true(trackEvent.track.muted);
t.done();
});
@@ -303,6 +373,54 @@
.catch(t.step_func(reason => {
assert_unreached(reason);
}));
- }, 'removeTrack() causes onmute and the track to be muted.');
+ }, 'removeTrack() makes track.onmute fire and the track to be muted.');
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ const remoteTrack = trackEvent.track;
+ const onmuteResolver = new Resolver();
+ remoteTrack.onmute = t.step_func(() => {
+ eventSequence += 'track.onmute;';
+ onmuteResolver.resolve();
+ });
+ caller.removeTrack(sender);
+ return Promise.all([
+ onmuteResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'track.onmute;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'track.onmute fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const pc = new RTCPeerConnection();
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = pc.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ pc.removeTrack(sender);
+ pc.removeTrack(sender);
+ t.done();
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'removeTrack() twice is safe.');
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
index 8617e7f4f97..72f544059ff 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
@@ -48,5 +48,5 @@ function validateCodecCapability(codec) {
}
function validateHeaderExtensionCapability(headerExt) {
- assert_optional_string_field(uri);
+ assert_optional_string_field(headerExt, 'uri');
}
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html b/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html
index 00aa680f53e..e5cb1eb99fa 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html
@@ -9,8 +9,8 @@
'use strict';
// Test is based on the following editor draft:
- // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
- // https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
+ // webrtc-pc 20171130
+ // webrtc-stats 20171122
// The following helper function is called from RTCStats-helper.js
// validateStatsReport
@@ -18,11 +18,6 @@
/*
5.2. RTCRtpSender Interface
- interface RTCRtpSender {
- Promise<RTCStatsReport> getStats();
- ...
- };
-
getStats
1. Let selector be the RTCRtpSender object on which the method was invoked.
2. Let p be a new promise, and run the following steps in parallel:
@@ -49,6 +44,22 @@
validateStatsReport(statsReport);
assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
});
- }, 'sender.getStats() should return stats report containing outbound-rtp stats');
+ }, 'sender.getStats() via addTransceiver should return stats report containing outbound-rtp stats');
+
+ promise_test(() => {
+ const pc = new RTCPeerConnection();
+
+ return navigator.mediaDevices.getUserMedia({ audio: true })
+ .then(mediaStream => {
+ const [track] = mediaStream.getTracks();
+ const sender = pc.addTrack(track, mediaStream);
+
+ return sender.getStats()
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ })
+ }, 'sender.getStats() via addTrack should return stats report containing outbound-rtp stats');
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html b/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html
new file mode 100644
index 00000000000..7d73cc5a3b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html
@@ -0,0 +1,181 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCSctpTransport.prototype.maxMessageSize</title>
+<link rel="help" href="https://w3c.github.io/webrtc-pc/#rtcsctptransport-interface">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+
+// This test has an assert_unreached() that requires that the variable
+// canSendSize (initiated below) is greater than 2, if non-zero. The reason
+// is that we need two non-zero values that are less that that value for
+// testing with predictable results. This is a bit unfortunate but shouldn't
+// have any practical impact.
+
+// Helper class to read SDP attributes and generate SDPs with modified attribute values
+class SDPAttributeHelper {
+ constructor(attrName, valueRegExpStr) {
+ this.attrName = attrName;
+ this.re = new RegExp(`^a=${attrName}:(${valueRegExpStr})\\r\\n`, 'm');
+ }
+
+ getValue(sdp) {
+ const matches = sdp.match(this.re);
+ return matches ? matches[1] : null;
+ }
+
+ sdpWithValue(sdp, value) {
+ const matches = sdp.match(this.re);
+ const sdpParts = sdp.split(matches[0]);
+ const attributeLine = arguments.length > 1 ? `a=${this.attrName}:${value}\r\n` : '';
+ return `${sdpParts[0]}${attributeLine}${sdpParts[1]}`;
+ }
+
+ sdpWithoutAttribute(sdp) {
+ return this.sdpWithValue(sdp);
+ }
+}
+
+const mmsAttributeHelper = new SDPAttributeHelper('max-message-size', '\\d+');
+let canSendSize;
+const remoteValue1 = 1;
+const remoteValue2 = 2;
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+ let maxMessageSize;
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, 0) };
+ return pc.setRemoteDescription(offer);
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ canSendSize = pc.sctp.maxMessageSize == Number.POSITIVE_INFINITY ? 0 : pc.sctp.maxMessageSize;
+ if (canSendSize != 0 && canSendSize < remoteValue2) {
+ assert_unreached('This test needs two values that are less than canSendSize (unless it is zero)');
+ }
+ });
+}, 'Determine the local side send limitation (canSendSize) by offering a max-message-size of 0');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ // Remove the max-message-size SDP attribute
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithoutAttribute(offer.sdp) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ // Test outcome depends on canSendSize value
+ if (canSendSize) {
+ assert_equals(pc.sctp.maxMessageSize, Math.min(65535, canSendSize),
+ 'Missing SDP attribute and a non-zero canSendSize should give an maxMessageSize of min(65535, canSendSize)');
+ } else {
+ assert_equals(pc.sctp.maxMessageSize, 65535,
+ 'Missing SDP attribute and a canSendSize of 0 should give an maxMessageSize of 65535');
+ }
+ });
+}, 'Remote offer SDP missing max-message-size attribute');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue1) };
+ return pc.setRemoteDescription(offer);
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue1,
+ 'maxMessageSize should be the value provided by the remote peer (as long as it is less than canSendSize)');
+ });
+}, 'max-message-size with a (non-zero) value provided by the remote peer');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue1) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue1,
+ 'maxMessageSize should be the value provided by the remote peer (as long as it is less than canSendSize)');
+ })
+ .then(() => pc.createOffer()) // Start new O/A exchange that updates max-message-size
+ .then((offer) => {
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue2)};
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue2,
+ 'maxMessageSize should be the new value provided by the remote peer (as long as it is less than canSendSize)');
+ })
+ ;
+}, 'Renegotiate max-message-size with a (non-zero) value provided by the remote peer');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+ const largerThanCanSendSize = canSendSize + 1;
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, largerThanCanSendSize) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ // Test outcome depends on canSendSize value
+ if (canSendSize) {
+ assert_equals(pc.sctp.maxMessageSize, canSendSize,
+ 'A remote value larger than a non-zero canSendSize should limit maxMessageSize to canSendSize');
+ } else {
+ assert_equals(pc.sctp.maxMessageSize, 65535,
+ 'A canSendSize of zero should let the remote value set maxMessageSize');
+ }
+ });
+}, 'max-message-size with a (non-zero) value larger than canSendSize provided by the remote peer');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
index 1ff3ae6711b..c2be1b3124f 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
@@ -1,18 +1,12 @@
'use strict';
// Test is based on the following editor draft:
-// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
-// https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
-
+// webrtc-pc 20171130
+// webrtc-stats 20171122
// This file depends on dictionary-helper.js which should
// be loaded from the main HTML file.
-// To improve readability, the WebIDL definitions of the Stats
-// dictionaries are modified to annotate with required fields when
-// they are required by section 8.6 of webrtc-pc. ID fields are
-// also annotated with the stats type that they are linked to.
-
/*
[webrtc-stats]
6.1. RTCStatsType enum
@@ -82,6 +76,16 @@ function assert_stats_report_has_stats(statsReport, statsTypes) {
}
}
+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) {
@@ -132,7 +136,7 @@ function validateOptionalIdField(statsReport, stats, field, type) {
};
*/
function validateRtcStats(statsReport, stats) {
- assert_number_field(stats, 'timeStamp');
+ assert_number_field(stats, 'timestamp');
assert_string_field(stats, 'type');
assert_string_field(stats, 'id');
}
@@ -141,35 +145,32 @@ function validateRtcStats(statsReport, stats) {
[webrtc-stats]
7.1. RTCRTPStreamStats dictionary
dictionary RTCRTPStreamStats : RTCStats {
- required unsigned long ssrc;
- required DOMString mediaType;
-
- [RTCMediaStreamTrackStats]
- required DOMString trackId;
-
- [RTCTransportStats]
- required DOMString transportId;
-
- [RTCCodecStats]
- required DOMString codecId;
-
- unsigned long firCount;
- unsigned long pliCount;
- required unsigned long nackCount;
- unsigned long sliCount;
- unsigned long long qpSum;
+ unsigned long ssrc;
+ DOMString mediaType;
+ DOMString trackId;
+ DOMString transportId;
+ DOMString codecId;
+ unsigned long firCount;
+ unsigned long pliCount;
+ unsigned long nackCount;
+ unsigned long sliCount;
+ unsigned long long qpSum;
};
+ mediaType of type DOMString
+ Either "audio" or "video".
+
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCRTPStreamStats, with attributes ssrc, associateStatsId, isRemote, mediaType,
- mediaTrackId, transportId, codecId, nackCount
+ - RTCRTPStreamStats, with attributes ssrc, mediaType, trackId,
+ transportId, codecId, nackCount
*/
function validateRtpStreamStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
assert_unsigned_int_field(stats, 'ssrc');
assert_string_field(stats, 'mediaType');
+ assert_enum_field(stats, 'mediaType', ['audio', 'video'])
validateIdField(statsReport, stats, 'trackId', 'track');
validateIdField(statsReport, stats, 'transportId', 'transport');
@@ -186,15 +187,12 @@ function validateRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.2. RTCCodecStats dictionary
dictionary RTCCodecStats : RTCStats {
- required unsigned long payloadType;
- required RTCCodecType codecType;
-
- [RTCTransportStats]
+ unsigned long payloadType;
+ RTCCodecType codecType;
DOMString transportId;
-
DOMString mimeType;
- required unsigned long clockRate;
- required unsigned long channels;
+ unsigned long clockRate;
+ unsigned long channels;
DOMString sdpFmtpLine;
DOMString implementation;
};
@@ -206,7 +204,7 @@ function validateRtpStreamStats(statsReport, stats) {
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCCodecStats, with attributes payloadType, codec, clockRate, channels, parameters
+ - RTCCodecStats, with attributes payloadType, codec, clockRate, channels, sdpFmtpLine
*/
function validateCodecStats(statsReport, stats) {
@@ -221,7 +219,7 @@ function validateCodecStats(statsReport, stats) {
assert_unsigned_int_field(stats, 'clockRate');
assert_unsigned_int_field(stats, 'channels');
- assert_optional_string_field(stats, 'sdpFmtpLine');
+ assert_string_field(stats, 'sdpFmtpLine');
assert_optional_string_field(stats, 'implementation');
}
@@ -229,34 +227,42 @@ function validateCodecStats(statsReport, stats) {
[webrtc-stats]
7.3. RTCReceivedRTPStreamStats dictionary
dictionary RTCReceivedRTPStreamStats : RTCRTPStreamStats {
- unsigned long packetsReceived;
- unsigned long long bytesReceived;
- unsigned long packetsLost;
- double jitter;
- double fractionLost;
- unsigned long packetsDiscarded;
- unsigned long packetsRepaired;
- unsigned long burstPacketsLost;
- unsigned long burstPacketsDiscarded;
- unsigned long burstLossCount;
- unsigned long burstDiscardCount;
- double burstLossRate;
- double burstDiscardRate;
- double gapLossRate;
- double gapDiscardRate;
+ unsigned long packetsReceived;
+ unsigned long long bytesReceived;
+ long packetsLost;
+ double jitter;
+ double fractionLost;
+ unsigned long packetsDiscarded;
+ unsigned long packetsFailedDecryption;
+ unsigned long packetsRepaired;
+ unsigned long burstPacketsLost;
+ unsigned long burstPacketsDiscarded;
+ unsigned long burstLossCount;
+ unsigned long burstDiscardCount;
+ double burstLossRate;
+ double burstDiscardRate;
+ double gapLossRate;
+ double gapDiscardRate;
};
+
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCReceivedRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes packetsReceived,
+ bytesReceived, packetsLost, jitter, packetsDiscarded
*/
function validateReceivedRtpStreamStats(statsReport, stats) {
validateRtpStreamStats(statsReport, stats);
- assert_optional_unsigned_int_field(stats, 'packetsReceived');
- assert_optional_unsigned_int_field(stats, 'bytesReceived');
- assert_optional_unsigned_int_field(stats, 'packetsLost');
+ assert_unsigned_int_field(stats, 'packetsReceived');
+ assert_unsigned_int_field(stats, 'bytesReceived');
+ assert_unsigned_int_field(stats, 'packetsLost');
- assert_optional_number_field(stats, 'jitter');
+ assert_number_field(stats, 'jitter');
assert_optional_number_field(stats, 'fractionLost');
- assert_optional_unsigned_int_field(stats, 'packetsDiscarded');
+ assert_unsigned_int_field(stats, 'packetsDiscarded');
+ assert_optional_unsigned_int_field(stats, 'packetsFailedDecryption');
assert_optional_unsigned_int_field(stats, 'packetsRepaired');
assert_optional_unsigned_int_field(stats, 'burstPacketsLost');
assert_optional_unsigned_int_field(stats, 'burstPacketsDiscarded');
@@ -273,37 +279,21 @@ function validateReceivedRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.4. RTCInboundRTPStreamStats dictionary
dictionary RTCInboundRTPStreamStats : RTCReceivedRTPStreamStats {
- required unsigned long packetsReceived;
- required unsigned long long bytesReceived;
- required unsigned long packetsLost;
- required double jitter;
- required unsigned long packetsDiscarded;
-
- [RTCRemoteOutboundRTPStreamStats]
DOMString remoteId;
-
unsigned long framesDecoded;
DOMHighResTimeStamp lastPacketReceivedTimestamp;
};
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCInboundRTPStreamStats, with all required attributes from RTCRTPStreamStats,
- and also attributes packetsReceived, bytesReceived, packetsLost, jitter,
- packetsDiscarded
+ - RTCInboundRTPStreamStats, with all required attributes from its inherited
+ dictionaries, and also attributes remoteId, framesDecoded
*/
function validateInboundRtpStreamStats(statsReport, stats) {
validateReceivedRtpStreamStats(statsReport, stats);
- assert_unsigned_int_field(stats, 'packetsReceived');
- assert_unsigned_int_field(stats, 'bytesReceived');
- assert_unsigned_int_field(stats, 'packetsLost');
- assert_number_field(stats, 'jitter');
- assert_unsigned_int_field(stats, 'packetsDiscarded');
-
- validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp');
-
- assert_optional_unsigned_int_field(stats, 'framesDecoded');
+ validateIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp');
+ assert_unsigned_int_field(stats, 'framesDecoded');
assert_optional_number_field(stats, 'lastPacketReceivedTimeStamp');
}
@@ -311,18 +301,20 @@ function validateInboundRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.5. RTCRemoteInboundRTPStreamStats dictionary
dictionary RTCRemoteInboundRTPStreamStats : RTCReceivedRTPStreamStats {
- [RTCOutboundRTPStreamStats]
- DOMString localId;
-
- double roundTripTime;
+ DOMString localId;
+ double roundTripTime;
};
- */
+ [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);
- validateOptionalIdField(statsReport, stats, 'localId', 'outbound-rtp');
- assert_optional_number_field(stats, 'roundTripTime');
+ validateIdField(statsReport, stats, 'localId', 'outbound-rtp');
+ assert_number_field(stats, 'roundTripTime');
}
/*
@@ -334,13 +326,18 @@ function validateRemoteInboundRtpStreamStats(statsReport, stats) {
unsigned long long bytesSent;
unsigned long long bytesDiscardedOnSend;
};
+
+ [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_optional_unsigned_int_field(stats, 'packetsSent');
+ assert_unsigned_int_field(stats, 'packetsSent');
assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend');
- assert_optional_unsigned_int_field(stats, 'bytesSent');
+ assert_unsigned_int_field(stats, 'bytesSent');
assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend');
}
@@ -348,12 +345,7 @@ function validateSentRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.7. RTCOutboundRTPStreamStats dictionary
dictionary RTCOutboundRTPStreamStats : RTCSentRTPStreamStats {
- required unsigned long packetsSent;
- required unsigned long long bytesSent;
-
- [RTCRemoteInboundRTPStreamStats]
DOMString remoteId;
-
DOMHighResTimeStamp lastPacketSentTimestamp;
double targetBitrate;
unsigned long framesEncoded;
@@ -361,20 +353,19 @@ function validateSentRtpStreamStats(statsReport, stats) {
double averageRTCPInterval;
};
- [webrtc-pc]
- 8.6. Mandatory To Implement Stats
- - RTCOutboundRTPStreamStats, with all required attributes from RTCRTPStreamStats,
- and also attributes packetsSent, bytesSent, roundTripTime
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCOutboundRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes remoteId, framesEncoded
*/
function validateOutboundRtpStreamStats(statsReport, stats) {
- validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp');
+ validateSentRtpStreamStats(statsReport, stats)
- assert_unsigned_int_field(stats, 'packetsSent');
- assert_unsigned_int_field(stats, 'bytesSent');
+ validateIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp');
assert_optional_number_field(stats, 'lastPacketSentTimestamp');
assert_optional_number_field(stats, 'targetBitrate');
- assert_optional_unsigned_int_field(stats, 'framesEncoded');
+ assert_unsigned_int_field(stats, 'framesEncoded');
assert_optional_number_field(stats, 'totalEncodeTime');
assert_optional_number_field(stats, 'averageRTCPInterval');
}
@@ -383,17 +374,20 @@ function validateOutboundRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.8. RTCRemoteOutboundRTPStreamStats dictionary
dictionary RTCRemoteOutboundRTPStreamStats : RTCSentRTPStreamStats {
- [RTCInboundRTPStreamStats]
DOMString localId;
-
DOMHighResTimeStamp remoteTimestamp;
};
+
+ [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);
- validateOptionalIdField(statsReport, stats, 'localId', 'inbound-rtp');
- assert_optional_number_field(stats, 'remoteTimeStamp');
+ validateIdField(statsReport, stats, 'localId', 'inbound-rtp');
+ assert_number_field(stats, 'remoteTimeStamp');
}
/*
@@ -401,10 +395,7 @@ function validateRemoteOutboundRtpStreamStats(statsReport, stats) {
7.9. RTCRTPContributingSourceStats
dictionary RTCRTPContributingSourceStats : RTCStats {
unsigned long contributorSsrc;
-
- [RTCInboundRTPStreamStats]
DOMString inboundRtpStreamId;
-
unsigned long packetsContributedTo;
double audioLevel;
};
@@ -423,10 +414,10 @@ function validateContributingSourceStats(statsReport, stats) {
[webrtc-stats]
7.10. RTCPeerConnectionStats dictionary
dictionary RTCPeerConnectionStats : RTCStats {
- required unsigned long dataChannelsOpened;
- required unsigned long dataChannelsClosed;
- unsigned long dataChannelsRequested;
- unsigned long dataChannelsAccepted;
+ unsigned long dataChannelsOpened;
+ unsigned long dataChannelsClosed;
+ unsigned long dataChannelsRequested;
+ unsigned long dataChannelsAccepted;
};
[webrtc-pc]
@@ -446,10 +437,8 @@ function validatePeerConnectionStats(statsReport, stats) {
[webrtc-stats]
7.11. RTCMediaStreamStats dictionary
dictionary RTCMediaStreamStats : RTCStats {
- required DOMString streamIdentifier;
-
- [RTCMediaStreamTrackStats]
- required sequence<DOMString> trackIds;
+ DOMString streamIdentifier;
+ sequence<DOMString> trackIds;
};
[webrtc-pc]
@@ -479,35 +468,37 @@ function validateMediaStreamStats(statsReport, stats) {
[webrtc-stats]
7.12. RTCMediaStreamTrackStats dictionary
dictionary RTCMediaStreamTrackStats : RTCStats {
- required DOMString trackIdentifier;
- required boolean remoteSource;
- required boolean ended;
- required boolean detached;
- DOMString kind;
- DOMHighResTimeStamp estimatedPlayoutTimestamp;
- required unsigned long frameWidth;
- required unsigned long frameHeight;
- required double framesPerSecond;
- unsigned long framesCaptured;
- required unsigned long framesSent;
- required unsigned long framesReceived;
- required unsigned long framesDecoded;
- required unsigned long framesDropped;
- required unsigned long framesCorrupted;
- unsigned long partialFramesLost;
- unsigned long fullFramesLost;
- required double audioLevel;
- double totalAudioEnergy;
- boolean voiceActivityFlag;
- double echoReturnLoss;
- double echoReturnLossEnhancement;
- unsigned long long totalSamplesSent;
- unsigned long long totalSamplesReceived;
- double totalSamplesDuration;
- unsigned long long concealedSamples;
- unsigned long long concealmentEvents;
- double jitterBufferDelay;
- RTCPriorityType priority;
+ DOMString trackIdentifier;
+ boolean remoteSource;
+ boolean ended;
+ boolean detached;
+ DOMString kind;
+ DOMHighResTimeStamp estimatedPlayoutTimestamp;
+ unsigned long frameWidth;
+ unsigned long frameHeight;
+ double framesPerSecond;
+ unsigned long framesCaptured;
+ unsigned long framesSent;
+ unsigned long keyFramesSent;
+ unsigned long framesReceived;
+ unsigned long keyFramesReceived;
+ unsigned long framesDecoded;
+ unsigned long framesDropped;
+ unsigned long framesCorrupted;
+ unsigned long partialFramesLost;
+ unsigned long fullFramesLost;
+ double audioLevel;
+ double totalAudioEnergy;
+ boolean voiceActivityFlag;
+ double echoReturnLoss;
+ double echoReturnLossEnhancement;
+ unsigned long long totalSamplesSent;
+ unsigned long long totalSamplesReceived;
+ double totalSamplesDuration;
+ unsigned long long concealedSamples;
+ unsigned long long concealmentEvents;
+ double jitterBufferDelay;
+ RTCPriorityType priority;
};
[webrtc-pc]
@@ -520,48 +511,50 @@ function validateMediaStreamStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCMediaStreamTrackStats, with attributes trackIdentifier, remoteSource, ended,
- detached, ssrcIds, frameWidth, frameHeight, framesPerSecond, framesSent,
+ - RTCMediaStreamTrackStats, with attributes trackIdentifier, remoteSource,
+ ended, detached, frameWidth, frameHeight, framesPerSecond, framesSent,
framesReceived, framesDecoded, framesDropped, framesCorrupted, audioLevel
*/
-function validateMediaStreamTrackStats(stats, stat) {
+function validateMediaStreamTrackStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
- assert_string_field(stat, 'trackIdentifier');
- assert_boolean_field(stat, 'remoteSource');
- assert_boolean_field(stat, 'ended');
- assert_boolean_field(stat, 'detached');
-
- assert_optional_string_field(stat, 'kind');
- assert_optional_number_field(stat, 'estimatedPlayoutTimestamp');
-
- assert_unsigned_int_field(stat, 'frameWidth');
- assert_unsigned_int_field(stat, 'frameHeight');
- assert_number_field(stat, 'framesPerSecond');
-
- assert_optional_unsigned_int_field(stat, 'framesCaptured');
- assert_unsigned_int_field(stat, 'frameSent');
- assert_unsigned_int_field(stat, 'frameReceived');
- assert_unsigned_int_field(stat, 'frameDecoded');
- assert_unsigned_int_field(stat, 'frameDropped');
- assert_unsigned_int_field(stat, 'frameCorrupted');
-
- assert_optional_unsigned_int_field(stat, 'partialFramesLost');
- assert_optional_unsigned_int_field(stat, 'fullFramesLost');
-
- assert_number_field(stat, 'audioLevel');
- assert_optional_number_field(stat, 'totalAudioEnergy');
- assert_optional_boolean_field(stat, 'voiceActivityFlag');
- assert_optional_number_field(stat, 'echoReturnLoss');
- assert_optional_number_field(stat, 'echoReturnLossEnhancement');
-
- assert_optional_unsigned_int_field(stat, 'totalSamplesSent');
- assert_optional_unsigned_int_field(stat, 'totalSamplesReceived');
- assert_optional_number_field(stat, 'totalSamplesDuration');
- assert_optional_unsigned_int_field(stat, 'concealedSamples');
- assert_optional_unsigned_int_field(stat, 'concealmentEvents');
- assert_optional_number_field(stat, 'jitterBufferDelay');
+ assert_string_field(stats, 'trackIdentifier');
+ assert_boolean_field(stats, 'remoteSource');
+ assert_boolean_field(stats, 'ended');
+ assert_boolean_field(stats, 'detached');
+
+ assert_optional_enum_field(stats, 'kind', ['audio', 'video']);
+ assert_optional_number_field(stats, 'estimatedPlayoutTimestamp');
+
+ assert_unsigned_int_field(stats, 'frameWidth');
+ assert_unsigned_int_field(stats, 'frameHeight');
+ assert_number_field(stats, 'framesPerSecond');
+
+ assert_optional_unsigned_int_field(stats, 'framesCaptured');
+ assert_unsigned_int_field(stats, 'framesSent');
+ assert_optional_unsigned_int_field(stats, 'keyFramesSent');
+ assert_unsigned_int_field(stats, 'framesReceived');
+ assert_optional_unsigned_int_field(stats, 'keyFramesReceived');
+ assert_unsigned_int_field(stats, 'framesDecoded');
+ assert_unsigned_int_field(stats, 'framesDropped');
+ assert_unsigned_int_field(stats, 'framesCorrupted');
+
+ assert_optional_unsigned_int_field(stats, 'partialFramesLost');
+ assert_optional_unsigned_int_field(stats, 'fullFramesLost');
+
+ assert_number_field(stats, 'audioLevel');
+ assert_optional_number_field(stats, 'totalAudioEnergy');
+ assert_optional_boolean_field(stats, 'voiceActivityFlag');
+ assert_optional_number_field(stats, 'echoReturnLoss');
+ assert_optional_number_field(stats, 'echoReturnLossEnhancement');
+
+ assert_optional_unsigned_int_field(stats, 'totalSamplesSent');
+ assert_optional_unsigned_int_field(stats, 'totalSamplesReceived');
+ assert_optional_number_field(stats, 'totalSamplesDuration');
+ assert_optional_unsigned_int_field(stats, 'concealedSamples');
+ assert_optional_unsigned_int_field(stats, 'concealmentEvents');
+ assert_optional_number_field(stats, 'jitterBufferDelay');
assert_optional_enum_field(stats, 'priority',
['very-low', 'low', 'medium', 'high']);
@@ -571,18 +564,15 @@ function validateMediaStreamTrackStats(stats, stat) {
[webrtc-stats]
7.13. RTCDataChannelStats dictionary
dictionary RTCDataChannelStats : RTCStats {
- required DOMString label;
- required DOMString protocol;
- required long datachannelid;
-
- [RTCTransportStats]
- DOMString transportId;
-
- required RTCDataChannelState state;
- required unsigned long messagesSent;
- required unsigned long long bytesSent;
- required unsigned long messagesReceived;
- required unsigned long long bytesReceived;
+ DOMString label;
+ DOMString protocol;
+ long dataChannelIdentifier;
+ DOMString transportId;
+ RTCDataChannelState state;
+ unsigned long messagesSent;
+ unsigned long long bytesSent;
+ unsigned long messagesReceived;
+ unsigned long long bytesReceived;
};
[webrtc-pc]
@@ -598,22 +588,19 @@ function validateMediaStreamTrackStats(stats, stat) {
- RTCDataChannelStats, with attributes label, protocol, datachannelId, state,
messagesSent, bytesSent, messagesReceived, bytesReceived
*/
-
function validateDataChannelStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
assert_string_field(stats, 'label');
assert_string_field(stats, 'protocol');
- assert_int_field(stats, 'datachannelid');
+ assert_int_field(stats, 'dataChannelIdentifier');
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
assert_enum_field(stats, 'state',
['connecting', 'open', 'closing', 'closed']);
- assert_unsigned_int_field(stats, 'messageSent');
-
- assert_unsigned_int_field(stats, 'messageSent');
+ assert_unsigned_int_field(stats, 'messagesSent');
assert_unsigned_int_field(stats, 'bytesSent');
assert_unsigned_int_field(stats, 'messagesReceived');
assert_unsigned_int_field(stats, 'bytesReceived');
@@ -623,25 +610,16 @@ function validateDataChannelStats(statsReport, stats) {
[webrtc-stats]
7.14. RTCTransportStats dictionary
dictionary RTCTransportStats : RTCStats {
- unsigned long packetsSent;
- unsigned long packetsReceived;
- required unsigned long long bytesSent;
- required unsigned long long bytesReceived;
-
- [RTCTransportStats]
- required DOMString rtcpTransportStatsId;
-
- RTCIceRole iceRole;
- RTCDtlsTransportState dtlsState;
-
- [RTCIceCandidatePairStats]
- required DOMString selectedCandidatePairId;
-
- [RTCCertificateStats]
- required DOMString localCertificateId;
-
- [RTCCertificateStats]
- required DOMString remoteCertificateId;
+ unsigned long packetsSent;
+ unsigned long packetsReceived;
+ unsigned long long bytesSent;
+ unsigned long long bytesReceived;
+ DOMString rtcpTransportStatsId;
+ RTCIceRole iceRole;
+ RTCDtlsTransportState dtlsState;
+ DOMString selectedCandidatePairId;
+ DOMString localCertificateId;
+ DOMString remoteCertificateId;
};
[webrtc-pc]
@@ -661,10 +639,10 @@ function validateDataChannelStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCTransportStats, with attributes bytesSent, bytesReceived, rtcpTransportStatsId,
- activeConnection, selectedCandidatePairId, localCertificateId, remoteCertificateId
+ - RTCTransportStats, with attributes bytesSent, bytesReceived,
+ rtcpTransportStatsId, selectedCandidatePairId, localCertificateId,
+ remoteCertificateId
*/
-
function validateTransportStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
@@ -682,26 +660,35 @@ function validateTransportStats(statsReport, stats) {
['new', 'connecting', 'connected', 'closed', 'failed']);
validateIdField(statsReport, stats, 'selectedCandidatePairId', 'candidate-pair');
- validateIdField(stateReport, stats, 'localCertificateId', 'certificate');
- validateIdField(stateReport, stats, 'remoteCertificateId', 'certificate');
+ validateIdField(statsReport, stats, 'localCertificateId', 'certificate');
+ validateIdField(statsReport, stats, 'remoteCertificateId', 'certificate');
}
/*
[webrtc-stats]
7.15. RTCIceCandidateStats dictionary
dictionary RTCIceCandidateStats : RTCStats {
- [RTCTransportStats]
- DOMString transportId;
-
- boolean isRemote;
- required DOMString ip;
- required long port;
- required DOMString protocol;
- required RTCIceCandidateType candidateType;
- required long priority;
- required DOMString url;
- DOMString relayProtocol;
- boolean deleted = false;
+ DOMString transportId;
+ boolean isRemote;
+ RTCNetworkType networkType;
+ DOMString ip;
+ long port;
+ DOMString protocol;
+ RTCIceCandidateType candidateType;
+ long priority;
+ DOMString url;
+ DOMString relayProtocol;
+ boolean deleted = false;
+ };
+
+ enum RTCNetworkType {
+ "bluetooth",
+ "cellular",
+ "ethernet",
+ "wifi",
+ "wimax",
+ "vpn",
+ "unknown"
};
[webrtc-pc]
@@ -714,16 +701,18 @@ function validateTransportStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCIceCandidateStats, with attributes ip, port, protocol, candidateType, priority,
- url
+ - RTCIceCandidateStats, with attributes ip, port, protocol, candidateType,
+ priority, url
*/
-
function validateIceCandidateStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
assert_optional_boolean_field(stats, 'isRemote');
+ assert_optional_enum_field(stats, 'networkType',
+ ['bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax', 'vpn', 'unknown'])
+
assert_string_field(stats, 'ip');
assert_int_field(stats, 'port');
assert_string_field(stats, 'protocol');
@@ -741,40 +730,34 @@ function validateIceCandidateStats(statsReport, stats) {
[webrtc-stats]
7.16. RTCIceCandidatePairStats dictionary
dictionary RTCIceCandidatePairStats : RTCStats {
- [RTCTransportStats]
- required DOMString transportId;
-
- [RTCIceCandidateStats]
- required DOMString localCandidateId;
-
- [RTCIceCandidateStats]
- required DOMString remoteCandidateId;
-
- required RTCStatsIceCandidatePairState state;
- required unsigned long long priority;
- required boolean nominated;
- unsigned long packetsSent;
- unsigned long packetsReceived;
- required unsigned long long bytesSent;
- required unsigned long long bytesReceived;
- DOMHighResTimeStamp lastPacketSentTimestamp;
- DOMHighResTimeStamp lastPacketReceivedTimestamp;
- DOMHighResTimeStamp firstRequestTimestamp;
- DOMHighResTimeStamp lastRequestTimestamp;
- DOMHighResTimeStamp lastResponseTimestamp;
- required double totalRoundTripTime;
- required 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;
+ DOMString transportId;
+ DOMString localCandidateId;
+ DOMString remoteCandidateId;
+ RTCStatsIceCandidatePairState state;
+ unsigned long long priority;
+ 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;
};
enum RTCStatsIceCandidatePairState {
@@ -788,8 +771,7 @@ function validateIceCandidateStats(statsReport, stats) {
[webrtc-pc]
8.6. Mandatory To Implement Stats
- RTCIceCandidatePairStats, with attributes transportId, localCandidateId,
- remoteCandidateId, state, priority, nominated, writable, readable, bytesSent,
- bytesReceived, totalRtt, currentRtt
+ remoteCandidateId, state, priority, nominated, bytesSent, bytesReceived, totalRoundTripTime, currentRoundTripTime
*/
function validateIceCandidatePairStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
@@ -835,10 +817,10 @@ function validateIceCandidatePairStats(statsReport, stats) {
[webrtc-stats]
7.17. RTCCertificateStats dictionary
dictionary RTCCertificateStats : RTCStats {
- required DOMString fingerprint;
- required DOMString fingerprintAlgorithm;
- required DOMString base64Certificate;
- required DOMString issuerCertificateId;
+ DOMString fingerprint;
+ DOMString fingerprintAlgorithm;
+ DOMString base64Certificate;
+ DOMString issuerCertificateId;
};
[webrtc-pc]
@@ -846,7 +828,6 @@ function validateIceCandidatePairStats(statsReport, stats) {
- RTCCertificateStats, with attributes fingerprint, fingerprintAlgorithm,
base64Certificate, issuerCertificateId
*/
-
function validateCertificateStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html b/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
index d5c5f621f80..9579dd4d4f8 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
@@ -41,6 +41,7 @@
assert_equals(trackEvent.receiver, receiver);
assert_equals(trackEvent.track, track);
assert_array_equals(trackEvent.streams, []);
+ assert_equals(trackEvent.streams, trackEvent.streams); // [SameObject]
assert_equals(trackEvent.transceiver, transceiver);
assert_equals(trackEvent.type, 'track');
diff --git a/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html b/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html
deleted file mode 100644
index ea2dd2a3df9..00000000000
--- a/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!doctype html>
-<!--
-This test creates a data channel object and compares it with the WebIDL defined interface
--->
-
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>RTCPeerConnection Data Channel Empty String Test</title>
- <link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
- <link rel="help" href="http://w3c.github.io/webrtc-pc/#rtcdatachannel">
-</head>
-<body>
- <div id="log"></div>
- <!-- These files are in place when executing on W3C. -->
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src=/resources/WebIDLParser.js></script>
- <script src=/resources/idlharness.js></script>
- <!-- The IDL is copied from https://w3c.github.io/webrtc-pc/archives/20161219/webrtc.html -->
- <script type="text/plain">
-interface RTCDataChannel : EventTarget {
- readonly attribute USVString label;
- readonly attribute boolean ordered;
- readonly attribute unsigned short? maxPacketLifeTime;
- readonly attribute unsigned short? maxRetransmits;
- readonly attribute USVString protocol;
- readonly attribute boolean negotiated;
- readonly attribute unsigned short id;
- readonly attribute RTCPriorityType priority;
- readonly attribute RTCDataChannelState readyState;
- readonly attribute unsigned long bufferedAmount;
- attribute unsigned long bufferedAmountLowThreshold;
- attribute EventHandler onopen;
- attribute EventHandler onbufferedamountlow;
- attribute EventHandler onerror;
- attribute EventHandler onclose;
- void close();
- attribute EventHandler onmessage;
- attribute DOMString binaryType;
- void send(USVString data);
- void send(Blob data);
- void send(ArrayBuffer data);
- void send(ArrayBufferView data);
-};
-enum RTCPriorityType {
- "very-low",
- "low",
- "medium",
- "high"
-};
-enum RTCDataChannelState {
- "connecting",
- "open",
- "closing",
- "closed"
-};
-</script>
- <script type="text/javascript">
- (function() {
- var idl_array = new IdlArray();
- [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"),
- function(node) {
- idl_array.add_idls(node.textContent);
- });
- pc = new RTCPeerConnection(null);
- window.channel = pc.createDataChannel("test");
- idl_array.add_objects({"RTCDataChannel": ["channel"]});
- idl_array.test();
- done();
-})();
-</script>
-</body>
-</html>
-
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js b/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js
new file mode 100644
index 00000000000..47bbb5dc024
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js
@@ -0,0 +1,156 @@
+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,
+ promise_rejects: 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_throws: true,
+ assert_idl_attribute: true,
+ assert_exists: 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.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,
+ doSignalingHandshake: true,
+ createDataChannelPair: true,
+ awaitMessage: true,
+ blobToArrayBuffer: true,
+ assert_equals_array_buffer: 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/tests/wpt/web-platform-tests/webrtc/tools/README.md b/tests/wpt/web-platform-tests/webrtc/tools/README.md
new file mode 100644
index 00000000000..68bc284fdfa
--- /dev/null
+++ b/tests/wpt/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/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json b/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json
new file mode 100644
index 00000000000..79e603949cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json
@@ -0,0 +1,1213 @@
+{
+ "name": "webrtc-testing-tools",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "acorn": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz",
+ "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
+ "requires": {
+ "acorn": "3.3.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true
+ }
+ }
+ },
+ "ajv": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz",
+ "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=",
+ "dev": true,
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.0.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+ "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "dev": true,
+ "requires": {
+ "callsites": "0.2.0"
+ }
+ },
+ "callsites": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.0.tgz",
+ "integrity": "sha1-C74TVaxE16PtSpJXB8TvcPgZD2w=",
+ "dev": true
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "typedarray": "0.0.6"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.1",
+ "shebang-command": "1.2.0",
+ "which": "1.3.0"
+ }
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "5.0.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "doctrine": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
+ "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
+ "dev": true,
+ "requires": {
+ "esutils": "2.0.2",
+ "isarray": "1.0.0"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.1.3",
+ "entities": "1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
+ "dev": true
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz",
+ "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0"
+ }
+ },
+ "domutils": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz",
+ "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0.1.0",
+ "domelementtype": "1.3.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz",
+ "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.3.0",
+ "babel-code-frame": "6.26.0",
+ "chalk": "2.3.0",
+ "concat-stream": "1.6.0",
+ "cross-spawn": "5.1.0",
+ "debug": "3.1.0",
+ "doctrine": "2.0.0",
+ "eslint-scope": "3.7.1",
+ "espree": "3.5.2",
+ "esquery": "1.0.0",
+ "estraverse": "4.2.0",
+ "esutils": "2.0.2",
+ "file-entry-cache": "2.0.0",
+ "functional-red-black-tree": "1.0.1",
+ "glob": "7.1.2",
+ "globals": "9.18.0",
+ "ignore": "3.3.7",
+ "imurmurhash": "0.1.4",
+ "inquirer": "3.3.0",
+ "is-resolvable": "1.0.0",
+ "js-yaml": "3.10.0",
+ "json-stable-stringify-without-jsonify": "1.0.1",
+ "levn": "0.3.0",
+ "lodash": "4.17.4",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "natural-compare": "1.4.0",
+ "optionator": "0.8.2",
+ "path-is-inside": "1.0.2",
+ "pluralize": "7.0.0",
+ "progress": "2.0.0",
+ "require-uncached": "1.0.3",
+ "semver": "5.4.1",
+ "strip-ansi": "4.0.0",
+ "strip-json-comments": "2.0.1",
+ "table": "4.0.2",
+ "text-table": "0.2.0"
+ }
+ },
+ "eslint-plugin-html": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.0.tgz",
+ "integrity": "sha512-xK/909qOTq5JVzuO2jo4a24nQcWhkOBz9dOIkORvB7RxC75a4b6B9wFpBXAl8WDhwJGFDj5gBDRN+/L3kK/ghw==",
+ "dev": true,
+ "requires": {
+ "htmlparser2": "3.9.2"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+ "dev": true,
+ "requires": {
+ "esrecurse": "4.2.0",
+ "estraverse": "4.2.0"
+ }
+ },
+ "espree": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
+ "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
+ "dev": true,
+ "requires": {
+ "acorn": "5.2.1",
+ "acorn-jsx": "3.0.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
+ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
+ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "external-editor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
+ "dev": true,
+ "requires": {
+ "chardet": "0.4.0",
+ "iconv-lite": "0.4.19",
+ "tmp": "0.0.33"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
+ "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "requires": {
+ "flat-cache": "1.3.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "dev": true,
+ "requires": {
+ "circular-json": "0.3.3",
+ "del": "2.2.2",
+ "graceful-fs": "4.1.11",
+ "write": "0.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "arrify": "1.0.1",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0",
+ "domhandler": "2.4.1",
+ "domutils": "1.6.2",
+ "entities": "1.1.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
+ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "3.0.0",
+ "chalk": "2.3.0",
+ "cli-cursor": "2.1.0",
+ "cli-width": "2.2.0",
+ "external-editor": "2.1.0",
+ "figures": "2.0.0",
+ "lodash": "4.17.4",
+ "mute-stream": "0.0.7",
+ "run-async": "2.3.0",
+ "rx-lite": "4.0.8",
+ "rx-lite-aggregates": "4.0.8",
+ "string-width": "2.1.1",
+ "strip-ansi": "4.0.0",
+ "through": "2.3.8"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
+ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-resolvable": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
+ "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=",
+ "dev": true,
+ "requires": {
+ "tryit": "1.0.3"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
+ "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "1.1.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "dev": true,
+ "requires": {
+ "caller-path": "0.1.0",
+ "resolve-from": "1.0.1"
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "2.0.1",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "2.1.0"
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
+ "dev": true
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "dev": true,
+ "requires": {
+ "rx-lite": "4.0.8"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.3.0",
+ "ajv-keywords": "2.1.1",
+ "chalk": "2.3.0",
+ "lodash": "4.17.4",
+ "slice-ansi": "1.0.0",
+ "string-width": "2.1.1"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "tryit": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
+ "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "requires": {
+ "mkdirp": "0.5.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/package.json b/tests/wpt/web-platform-tests/webrtc/tools/package.json
new file mode 100644
index 00000000000..70515d8b715
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "webrtc-testing-tools",
+ "version": "1.0.0",
+ "description": "Tools for WebRTC testing",
+ "scripts": {
+ "lint": "eslint -c .eslintrc.js ../*.html ../*.js"
+ },
+ "devDependencies": {
+ "eslint": "^4.11.0",
+ "eslint-plugin-html": "^4.0.0"
+ },
+ "license": "BSD",
+ "private": true
+}