Updated W3C getusermedia tests to the latest version of the spec.
BUG=webrtc:3455
R=kjellander@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16719004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6459 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/test/w3c/getusermedia_conformance_test.html b/webrtc/test/w3c/getusermedia_conformance_test.html
index 6ddb603..7b724a9 100644
--- a/webrtc/test/w3c/getusermedia_conformance_test.html
+++ b/webrtc/test/w3c/getusermedia_conformance_test.html
@@ -52,15 +52,16 @@
</p>
<div id="log"></div>
- <video id="local-view" autoplay="autoplay" muted="true"></video>
-
<!-- These files are in place when executing on W3C. -->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/vendor-prefix.js"
- data-prefixed-objects= '[{"ancestors":["navigator"], "name":"getUserMedia"},
- {"ancestors":["window"], "name":"RTCPeerConnection"}]'
- data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
+ data-prefixed-objects=
+ '[{"ancestors":["navigator"], "name":"getUserMedia"},
+ {"ancestors":["window"], "name":"RTCPeerConnection"}]'
+ data-prefixed-prototypes=
+ '[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'>
+ </script>
<script src="getusermedia_conformance_test.js"></script>
</body>
diff --git a/webrtc/test/w3c/getusermedia_conformance_test.js b/webrtc/test/w3c/getusermedia_conformance_test.js
index fe1dcc8..d7c7828 100644
--- a/webrtc/test/w3c/getusermedia_conformance_test.js
+++ b/webrtc/test/w3c/getusermedia_conformance_test.js
@@ -6,7 +6,7 @@
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
-setup({timeout:10000});
+setup({timeout:5000});
// Helper functions to minimize code duplication.
function failedCallback(test) {
@@ -19,6 +19,14 @@
failedCallback(test));
}
+function createInvisibleVideoTag() {
+ var video = document.createElement('video');
+ video.autoplay = true;
+ video.style.display = 'none';
+ document.body.appendChild(video);
+ return video;
+}
+
// 4.2 MediaStream.
var mediaStreamTest = async_test('4.2 MediaStream');
@@ -56,21 +64,25 @@
}, '[MediaStream] removeTrack function');
test(function () {
- // Missing in Chrome.
assert_inherits(stream, 'clone');
assert_true(typeof stream.clone === 'function');
}, '[MediaStream] clone function');
test(function () {
- assert_own_property(stream, 'ended');
- assert_true(typeof stream.ended === 'boolean');
- assert_readonly(stream, 'ended');
- }, '[MediaStream] ended attribute');
+ assert_own_property(stream, 'active');
+ assert_true(typeof stream.active === 'boolean');
+ assert_readonly(stream, 'active');
+ }, '[MediaStream] active attribute');
test(function () {
- assert_own_property(stream, 'onended');
- assert_true(stream.onended === null);
- }, '[MediaStream] onended EventHandler');
+ assert_own_property(stream, 'onactive');
+ assert_true(stream.onactive === null);
+ }, '[MediaStream] onactive EventHandler');
+
+ test(function () {
+ assert_own_property(stream, 'oninactive');
+ assert_true(stream.oninactive === null);
+ }, '[MediaStream] oninactive EventHandler');
test(function () {
assert_own_property(stream, 'onaddtrack');
@@ -86,28 +98,43 @@
mediaStreamTest.step(function() {
var okCallback = mediaStreamTest.step_func(function (stream) {
verifyMediaStream(stream);
-
var videoTracks = stream.getVideoTracks();
assert_true(videoTracks.length > 0);
+ mediaStreamTest.done();
+ });
- // Verify event handlers are working.
- stream.onaddtrack = onAddTrackCallback
- stream.onremovetrack = onRemoveTrackCallback
- stream.removeTrack(videoTracks[0]);
- stream.addTrack(videoTracks[0]);
- mediaStreamTest.done();
- });
- var onAddTrackCallback = mediaStreamTest.step_func(function () {
- // TODO(kjellander): verify number of tracks.
- mediaStreamTest.done();
- });
- var onRemoveTrackCallback = mediaStreamTest.step_func(function () {
- // TODO(kjellander): verify number of tracks.
- mediaStreamTest.done();
- });
invokeGetUserMedia(mediaStreamTest, okCallback);
});
+var mediaStreamCallbacksTest = async_test('4.2.2 MediaStream callbacks');
+
+mediaStreamCallbacksTest.step(function() {
+ var addCallbackCalled = false;
+ var onAddTrackCallback = mediaStreamCallbacksTest.step_func(function (event) {
+ assert_true(event.track instanceof MediaStreamTrack);
+ addCallbackCalled = true;
+ });
+ var onRemoveTrackCallback =
+ mediaStreamCallbacksTest.step_func(function (event) {
+ assert_true(event.track instanceof MediaStreamTrack);
+ assert_true(addCallbackCalled, 'Add should have been called after remove.');
+ mediaStreamCallbacksTest.done();
+ });
+ var okCallback = mediaStreamCallbacksTest.step_func(function (stream) {
+ var videoTracks = stream.getVideoTracks();
+
+ // Verify event handlers are working.
+ stream.onaddtrack = onAddTrackCallback;
+ stream.onremovetrack = onRemoveTrackCallback;
+ stream.removeTrack(videoTracks[0]);
+ stream.addTrack(videoTracks[0]);
+ });
+
+ invokeGetUserMedia(mediaStreamCallbacksTest, okCallback);
+});
+
+// TODO(phoglund): add test for onactive/oninactive.
+
// 4.3 MediaStreamTrack.
var mediaStreamTrackTest = async_test('4.3 MediaStreamTrack');
@@ -140,7 +167,6 @@
}, '[MediaStreamTrack (' + type + ')] enabled attribute');
test(function () {
- // Missing in Chrome.
assert_own_property(track, 'muted');
assert_readonly(track, 'muted');
assert_true(typeof track.muted === 'boolean');
@@ -250,59 +276,113 @@
var mediaStreamTrackEventTest = async_test('4.4 MediaStreamTrackEvent');
mediaStreamTrackEventTest.step(function() {
var okCallback = mediaStreamTrackEventTest.step_func(function (stream) {
- // TODO(kjellander): verify attributes
+ // TODO(kjellander): verify attributes.
mediaStreamTrackEventTest.done();
});
invokeGetUserMedia(mediaStreamTrackEventTest, okCallback);
});
-// 4.5 Video and Audio Tracks tests.
-var avTracksTest = async_test('4.5 Video and Audio Tracks');
-avTracksTest.step(function() {
- var okCallback = avTracksTest.step_func(function (stream) {
- // TODO(kjellander): verify attributes
- avTracksTest.done();
+// 6. Media streams as media elements.
+
+var playingInMediaElementTest = async_test(
+ '6.2 Loading and Playing a MediaStream in a Media Element');
+playingInMediaElementTest.step(function() {
+ var video = createInvisibleVideoTag();
+
+ var okCallback = playingInMediaElementTest.step_func(function (stream) {
+ video.onplay = playingInMediaElementTest.step_func(function() {
+ // This depends on what webcam we're actually running with, but the
+ // resolution should at least be greater than or equal to QVGA.
+ assert_greater_than_equal(video.videoWidth, 320);
+ assert_greater_than_equal(video.videoHeight, 240);
+
+ playingInMediaElementTest.done();
+ });
+ video.srcObject = stream;
});
- invokeGetUserMedia(avTracksTest, okCallback);
+ invokeGetUserMedia(playingInMediaElementTest, okCallback);
});
-// 5. The model: sources, sinks, constraints, and states
+// Verifies a media element track (for instance belonging to a video tag)
+// after it has been assigned a media stream.
+function verifyOneMediaElementTrack(track, correspondingMediaStreamTrack) {
+ assert_equals(track.id, correspondingMediaStreamTrack.id);
+ assert_equals(track.kind, 'main');
+ assert_equals(track.label, correspondingMediaStreamTrack.label);
+ assert_equals(track.language, '');
+}
-// 6. Source states
-// 6.1 Dictionary MediaSourceStates Members
+var setsUpMediaTracksRightTest = async_test(
+ '6.2 Sets up <video> audio and video tracks right');
+setsUpMediaTracksRightTest.step(function() {
+ var video = createInvisibleVideoTag();
-// 7. Source capabilities
-// 7.1 Dictionary CapabilityRange Members
-// 7.2 CapabilityList array
-// 7.3 Dictionary AllVideoCapabilities Members
-// 7.4 Dictionary AllAudioCapabilities Members
+ var okCallback = setsUpMediaTracksRightTest.step_func(function (stream) {
+ video.onplay = setsUpMediaTracksRightTest.step_func(function() {
+ // Verify the requirements on the video tag's streams as outlined in 6.2.
+ // There could be any number of tracks depending on what device we have
+ // connected, so verify all of them. There should be at least one of audio
+ // and video each though.
+ assert_inherits(video, 'videoTracks',
+ 'Browser missing videoTracks support on media elements.');
+ assert_readonly(video, 'videoTracks');
+ assert_greater_than_equal(video.videoTracks.length, 1);
+ assert_equals(video.videoTracks.length, stream.getVideoTracks().length);
-// 8. URL tests.
-var createObjectURLTest = async_test('8.1 URL createObjectURL method');
-createObjectURLTest.step(function() {
- var okCallback = createObjectURLTest.step_func(function (stream) {
- var url = URL.createObjectURL(stream);
- assert_true(typeof url === 'string');
- createObjectURLTest.done();
+ for (var i = 0; i < video.videoTracks.length; i++) {
+ verifyOneMediaElementTrack(video.videoTracks[i],
+ stream.getVideoTracks()[i]);
+ }
+
+ assert_inherits(video, 'audioTracks',
+ 'Browser missing audioTracks support on media elements.');
+ assert_readonly(video, 'audioTracks');
+ assert_greater_than_equal(video.audioTracks.length, 1);
+ assert_equals(video.audioTracks.length, stream.getAudioTracks().length);
+
+ for (var i = 0; i < video.audioTracks.length; i++) {
+ verifyOneMediaElementTrack(audio.audioTracks[i],
+ stream.getAudioTracks()[i]);
+ }
+
+ setsUpMediaTracksRightTest.done();
+ });
+ video.srcObject = stream;
});
- invokeGetUserMedia(createObjectURLTest, okCallback);
+ invokeGetUserMedia(setsUpMediaTracksRightTest, okCallback);
});
-// 9. MediaStreams as Media Elements.
-var mediaElementsTest = async_test('9. MediaStreams as Media Elements');
+var mediaElementsTest =
+ async_test('6.3 Media Element Attributes when Playing a MediaStream');
function verifyVideoTagWithStream(videoTag) {
test(function () {
+ assert_equals(videoTag.currentSrc, '');
+ }, '[Video tag] currentSrc attribute');
+
+ test(function () {
+ assert_equals(videoTag.preload, 'none');
+ }, '[Video tag] preload attribute');
+
+ test(function () {
assert_equals(videoTag.buffered.length, 0);
}, '[Video tag] buffered attribute');
test(function () {
- // Attempts to alter currentTime shall be ignored.
+ // Where 1 is NETWORK_IDLE.
+ assert_equals(videoTag.networkState, 1);
+ }, '[Video tag] networkState attribute');
+
+ test(function () {
+ // 0 is HAVE_NOTHING, 4 is HAVE_ENOUGH_DATA.
+ assert_true(videoTag.readyState == 0 || videoTag.readyState == 4);
+ }, '[Video tag] readyState attribute');
+
+ test(function () {
assert_true(videoTag.currentTime >= 0);
- assert_throws('InvalidStateError',
- function () { videoTag.currentTime = 1234; },
- 'Attempts to modify currentTime shall throw ' +
- 'InvalidStateError');
+ assert_throws(
+ 'InvalidStateError', function () { videoTag.currentTime = 1234; },
+ 'Attempts to modify currentTime shall throw InvalidStateError');
}, '[Video tag] currentTime attribute');
test(function () {
@@ -315,16 +395,16 @@
test(function () {
assert_equals(videoTag.defaultPlaybackRate, 1.0);
- assert_throws('DOMException',
- function () { videoTag.defaultPlaybackRate = 2.0; },
- 'Attempts to alter videoTag.defaultPlaybackRate MUST fail');
+ assert_throws(
+ 'DOMException', function () { videoTag.defaultPlaybackRate = 2.0; },
+ 'Attempts to alter videoTag.defaultPlaybackRate MUST fail');
}, '[Video tag] defaultPlaybackRate attribute');
test(function () {
assert_equals(videoTag.playbackRate, 1.0);
- assert_throws('DOMException',
- function () { videoTag.playbackRate = 2.0; },
- 'Attempts to alter videoTag.playbackRate MUST fail');
+ assert_throws(
+ 'DOMException', function () { videoTag.playbackRate = 2.0; },
+ 'Attempts to alter videoTag.playbackRate MUST fail');
}, '[Video tag] playbackRate attribute');
test(function () {
@@ -335,56 +415,96 @@
test(function () {
assert_equals(videoTag.seekable.length, 0);
- assert_equals(videoTag.seekable.start(), videoTag.currentTime);
- assert_equals(videoTag.seekable.end(), videoTag.currentTime);
- assert_equals(videoTag.startDate, NaN, 'videoTag.startDate');
+ // This is wrong in the standard: start() and end() must have arguments, but
+ // since the time range is empty as we assert in the line above, there is no
+ // valid argument with which we can call the methods.
+ // assert_equals(videoTag.seekable.start(), videoTag.currentTime);
+ // assert_equals(videoTag.seekable.end(), videoTag.currentTime);
}, '[Video tag] seekable attribute');
test(function () {
+ assert_equals(videoTag.startDate, NaN, 'videoTag.startDate');
+ }, '[Video tag] startDate attribute');
+
+ test(function () {
assert_false(videoTag.loop);
}, '[Video tag] loop attribute');
+
};
mediaElementsTest.step(function() {
var okCallback = mediaElementsTest.step_func(function (stream) {
- var videoTag = document.getElementById('local-view');
- videoTag.srcObject = stream;
- verifyVideoTagWithStream(videoTag);
+ var video = createInvisibleVideoTag();
+ video.srcObject = stream;
+ verifyVideoTagWithStream(video);
mediaElementsTest.done();
});
invokeGetUserMedia(mediaElementsTest, okCallback);
});
-// 11. Obtaining local multimedia content.
+// 9. Enumerating local media devices.
+// TODO(phoglund): add tests.
-// 11.1 NavigatorUserMedia.
-var getUserMediaTest = async_test('11.1 NavigatorUserMedia');
-getUserMediaTest.step(function() {
- var okCallback = getUserMediaTest.step_func(function (stream) {
+// 10. Obtaining local multimedia content.
+
+function testGetUserMedia(test, constraints) {
+ var okCallback = test.step_func(function (stream) {
assert_true(stream !== null);
- getUserMediaTest.done();
+ test.done();
});
+ navigator.getUserMedia(constraints, okCallback, failedCallback(test));
+}
- // All three arguments are mandatory, so pass all of them.
- navigator.getUserMedia({ video: true, audio: true }, okCallback,
- failedCallback(getUserMediaTest));
- navigator.getUserMedia({ video: true, audio: false }, okCallback,
- failedCallback(getUserMediaTest));
- navigator.getUserMedia({ video: false, audio: true }, okCallback,
- failedCallback(getUserMediaTest));
+var getUserMediaTestAudioVideo = async_test('10.1.1 NavigatorUserMedia A/V');
+getUserMediaTestAudioVideo.step(function() {
+ testGetUserMedia(getUserMediaTestAudioVideo, { video: true, audio: true });
});
-// 11.2 MediaStreamConstraints.
-var constraintsTest = async_test('11.2 MediaStreamConstraints');
+var getUserMediaTestVideo = async_test('10.1.1 NavigatorUserMedia V');
+getUserMediaTestVideo.step(function() {
+ testGetUserMedia(getUserMediaTestVideo, { video: true, audio: false });
+});
+
+var getUserMediaTestAudio = async_test('10.1.1 NavigatorUserMedia A');
+getUserMediaTestAudio.step(function() {
+ testGetUserMedia(getUserMediaTestAudio, { video: false, audio: true });
+});
+
+var getUserMediaTestNull = async_test('10.1.1 NavigatorUserMedia Null');
+getUserMediaTestNull.step(function() {
+ testGetUserMedia(getUserMediaTestNull, null);
+});
+
+var getUserMediaTestPeerIdentity =
+ async_test('10.2 NavigatorUserMedia with peerIdentity');
+getUserMediaTestPeerIdentity.step(function() {
+ var peerIdentity = 'my_identity';
+ var okCallback = getUserMediaTestPeerIdentity.step_func(function (stream) {
+ assert_true(stream !== null);
+ stream.getVideoTracks().forEach(function(track) {
+ assert_equals(track.peerIdentity, peerIdentity);
+ });
+ stream.getAudioTracks().forEach(function(track) {
+ assert_equals(track.peerIdentity, peerIdentity);
+ });
+ getUserMediaTestPeerIdentity.done();
+ });
+ navigator.getUserMedia(
+ {video: true, audio: true, peerIdentity: 'my_identity' },
+ okCallback, failedCallback(getUserMediaTestPeerIdentity));
+});
+
+// 10.2 MediaStreamConstraints.
+var constraintsTest = async_test('10.2 MediaStreamConstraints');
constraintsTest.step(function() {
var okCallback = constraintsTest.step_func(function (stream) {
assert_true(stream !== null);
constraintsTest.done();
});
- // Constraints on video.
- // See http://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/constraints-and-stats.html
+ // See https://googlechrome.github.io/webrtc/samples/web/content/constraints/
// for more examples of constraints.
+ // TODO(phoglund): test more constraints; the possibilities here are endless.
var constraints = {};
constraints.audio = true;
constraints.video = { mandatory: {}, optional: [] };
@@ -396,9 +516,9 @@
failedCallback(constraintsTest));
});
-// 11.3 NavigatorUserMediaSuccessCallback.
+// 10.4 NavigatorUserMediaSuccessCallback.
var successCallbackTest =
- async_test('11.3 NavigatorUserMediaSuccessCallback');
+ async_test('10.4 NavigatorUserMediaSuccessCallback');
successCallbackTest.step(function() {
var okCallback = successCallbackTest.step_func(function (stream) {
assert_true(stream !== null);
@@ -407,3 +527,5 @@
invokeGetUserMedia(successCallbackTest, okCallback);
});
+// 11. Constrainable Pattern.
+// TODO(phoglund): add tests.