Bug 781534 - Create basic automated test coverage for the mozGetUserMedia for desktop. r=roc

This commit is contained in:
Jason Smith 2012-11-26 18:27:46 -08:00
parent 6aa8ba56de
commit efdb4afbe1
7 changed files with 339 additions and 8 deletions

View File

@ -10,7 +10,12 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES = \
# TODO: When bug 814718 and bug 814721 are fixed, add the following files:
# test_getUserMedia_basicVideo.html
# test_getUserMedia_basicAudio.thml
# test_getUserMedia_basicVideoAudio.html
# mediaStreamPlayback.js
MOCHITEST_FILES = \
test_getUserMedia_exceptions.html \
head.js \
$(NULL)

View File

@ -1,4 +1,4 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -9,14 +9,33 @@ var Cr = SpecialPowers.Cr;
/**
* Setup any Mochitest for WebRTC by enabling the preference for
* peer connections. As by bug 797979 it will also enable mozGetUserMedia().
* Additionally, we disable the permissions prompt for these mochitests.
*
* @param {Function} aCallback Test method to execute after initialization
* @param {Boolean} desktopSupportedOnly specifies if the test currently
* is known to work on desktop only
*/
function runTest(aCallback) {
function runTest(aCallback, desktopSupportedOnly) {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [['media.peerconnection.enabled', true],
['media.navigator.permission.disabled', true]]},
aCallback);
// If this is a desktop supported test and we're on android or b2g,
// indicate that the test is not supported and skip the test
if(desktopSupportedOnly && (navigator.platform === 'Android' ||
navigator.platform === '')) {
ok(true, navigator.platform + ' currently not supported');
SimpleTest.finish();
} else {
SpecialPowers.pushPrefEnv({'set': [['media.peerconnection.enabled', true]]},
aCallback);
}
}
/**
* A callback function fired only under unexpected circumstances while
* running the tests. Kills off the test as well gracefully.
*
* @param {String} obj the object fired back from the callback
*/
function unexpectedCallbackAndFinish(obj) {
ok(false, "Unexpected error callback with " + obj);
SimpleTest.finish();
}

View File

@ -0,0 +1,167 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This class manages playback of a HTMLMediaElement with a MediaStream.
* When constructed by a caller, an object instance is created with
* a media element and a media stream object.
*
* @param {HTMLMediaElement} mediaElement the media element for playback
* @param {LocalMediaStream} mediaStream the media stream used in
* the mediaElement for playback
*/
function MediaStreamPlayback(mediaElement, mediaStream) {
/** The HTMLMediaElement used for media playback */
this.mediaElement = mediaElement;
/** The LocalMediaStream used with the HTMLMediaElement */
this.mediaStream = mediaStream;
/**
* Starts the media with the associated stream.
*
* @param {Integer} timeoutLength the timeout length to wait for
* canplaythrough to fire in milliseconds
* @param {Function} onSuccess the success function call back
* if media starts correctly
* @param {Function} onError the error function call back
* if media fails to start
*/
this.startMedia = function(timeoutLength, onSuccess, onError) {
var self = this;
var canPlayThroughFired = false;
// Verifies we've received a correctly initialized LocalMediaStream
ok(this.mediaStream instanceof LocalMediaStream,
"Stream should be a LocalMediaStream");
is(this.mediaStream.currentTime, 0,
"Before starting the media element, currentTime = 0");
/**
* Callback fired when the canplaythrough event is fired. We only
* run the logic of this function once, as this event can fire
* multiple times while a HTMLMediaStream is playing content from
* a real-time MediaStream.
*/
var canPlayThroughCallback = function() {
// Disable the canplaythrough event listener to prevent multiple calls
canPlayThroughFired = true;
self.mediaElement.removeEventListener('canplaythrough',
canPlayThroughCallback, false);
is(self.mediaElement.paused, false,
"Media element should be playing");
is(self.mediaElement.ended, false,
"Media element should not have ended");
is(self.mediaElement.duration, Number.POSITIVE_INFINITY,
"Duration should be infinity");
// When the media element is playing with a real-time stream, we
// constantly switch between having data to play vs. queuing up data,
// so we can only check that the ready state is one of those two values
ok(self.mediaElement.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA ||
self.mediaElement.readyState === HTMLMediaElement.HAVE_CURRENT_DATA,
"Ready state shall be HAVE_ENOUGH_DATA or HAVE_CURRENT_DATA");
is(self.mediaElement.seekable.length, 0,
"Seekable length shall be zero");
is(self.mediaElement.buffered.length, 0,
"Buffered length shall be zero");
is(self.mediaElement.played.length, 1, "Played length shall be one");
if(self.mediaElement.played.length > 0) {
is(self.mediaElement.played.start(0), 0,
"Played start shall be zero");
is(self.mediaElement.played.end(0), self.mediaElement.currentTime,
"End shall be current time");
}
is(self.mediaElement.seeking, false,
"MediaElement is not seekable with MediaStream");
ok(isNaN(self.mediaElement.startOffsetTime),
"Start offset time shall not be a number");
is(self.mediaElement.loop, false, "Loop shall be false");
is(self.mediaElement.preload, "", "Preload should not exist");
is(self.mediaElement.src, "", "No src should be defined");
is(self.mediaElement.currentSrc, "",
"Current src should still be an empty string");
var timeUpdateFired = false;
var timeUpdateCallback = function() {
timeUpdateFired = true;
self.mediaElement.removeEventListener('timeupdate', timeUpdateCallback,
false);
ok(self.mediaStream.currentTime > 0,
"Stream's time should be greater than zero");
ok(self.mediaElement.currentTime > 0,
"MediaElement time shall be greater than zero");
onSuccess();
};
// When timeupdate fires, we validate time has passed and move
// onto the success condition
self.mediaElement.addEventListener('timeupdate', timeUpdateCallback,
false);
// If timeupdate doesn't fire in enough time, we fail the test
setTimeout(function() {
if(!timeUpdateFired) {
ok(false, "timeUpdate event never fired");
onError();
}
}, timeoutLength);
};
// Adds a listener intended to be fired when playback is available
// without further buffering.
this.mediaElement.addEventListener('canplaythrough', canPlayThroughCallback,
false);
// Hooks up the media stream to the media element and starts playing it
this.mediaElement.mozSrcObject = mediaStream;
this.mediaElement.play();
// If canplaythrough doesn't fire in enough time, we fail the test
setTimeout(function() {
if(!canPlayThroughFired) {
ok(false, "canplaythrough event never fired");
onError();
}
}, timeoutLength);
};
/**
* Stops the media with the associated stream.
*
* Precondition: The media stream and element should both be actively
* being played.
*/
this.stopMedia = function() {
this.mediaElement.pause();
this.mediaElement.mozSrcObject = null;
};
/**
* Starts media with a media stream, runs it until a canplaythrough and
* timeupdate event fires, and stops the media.
*
* @param {Integer} timeoutLength the length of time to wait for certain
* media events to fire
* @param {Function} onSuccess the success callback if the media playback
* start and stop cycle completes successfully
* @param {Function} onError the error callback if the media playback
* start and stop cycle fails
*/
this.playMedia = function(timeoutLength, onSuccess, onError) {
var self = this;
this.startMedia(timeoutLength, function() {
self.stopMedia();
onSuccess();
}, onError);
};
}

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=781534
-->
<head>
<meta charset="utf-8">
<title>mozGetUserMedia Basic Audio Test</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<audio id="testAudio"></audio>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Audio Test</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Run a test to verify that we can complete a start and stop media playback
* cycle for an audio LocalMediaStream on an audio HTMLMediaElement.
*/
runTest(function () {
try {
navigator.mozGetUserMedia({audio: true, fake: true}, function(stream) {
var testAudio = document.getElementById('testAudio');
var audioStreamPlayback = new MediaStreamPlayback(testAudio, stream);
audioStreamPlayback.playMedia(5000, function() {
stream.stop();
SimpleTest.finish();
}, unexpectedCallbackAndFinish);
}, unexpectedCallbackAndFinish);
} catch (err) {
unexpectedCallbackAndFinish(err);
}
}, true);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=781534
-->
<head>
<meta charset="utf-8">
<title>mozGetUserMedia Basic Video Test</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<video id="testVideo"></video>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Video Test</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Run a test to verify that we can complete a start and stop media playback
* cycle for an video LocalMediaStream on a video HTMLMediaElement.
*/
runTest(function () {
try {
navigator.mozGetUserMedia({video: true, fake: true}, function(stream) {
var testVideo = document.getElementById('testVideo');
var videoStreamPlayback = new MediaStreamPlayback(testVideo, stream);
videoStreamPlayback.playMedia(5000, function() {
stream.stop();
SimpleTest.finish();
}, unexpectedCallbackAndFinish);
}, unexpectedCallbackAndFinish);
} catch (err) {
unexpectedCallbackAndFinish(err);
}
}, true);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=781534
-->
<head>
<meta charset="utf-8">
<title>mozGetUserMedia Basic Video & Audio Test</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<video id="testVideoAudio"></video>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=781534">mozGetUserMedia Basic Video & Audio Test</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Run a test to verify that we can complete a start and stop media playback
* cycle for a video and audio LocalMediaStream on a video HTMLMediaElement.
*/
runTest(function () {
try {
navigator.mozGetUserMedia({video: true, audio: true, fake: true},
function(stream) {
var testVideoAudio = document.getElementById('testVideoAudio');
var videoAudioStreamPlayback = new MediaStreamPlayback(testVideoAudio,
stream);
videoAudioStreamPlayback.playMedia(5000, function() {
stream.stop();
SimpleTest.finish();
}, unexpectedCallbackAndFinish);
}, unexpectedCallbackAndFinish);
} catch (err) {
unexpectedCallbackAndFinish(err);
}
}, true);
</script>
</pre>
</body>
</html>

View File

@ -78,7 +78,7 @@ runTest(function () {
});
SimpleTest.finish();
});
}, false);
</script>
</pre>