Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Unified Diff: third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html

Issue 2115143002: Transition media element to HAVE_CURRENT_DATA upon underflow. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Feedback Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html
index 7f6a9a103fb607745478c9040d5e244e77f00723..0e99c95e121e08398605b5734cc246fd24fcdab8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html
@@ -1,43 +1,114 @@
-<video></video>
-<p>Test that stalled, timeupdate and waiting events are sent when media load stalls in the middle.</p>
+<!DOCTYPE html>
+<title>Test that stalled, timeupdate and waiting events are sent when media load stalls in the middle.</title>
+<video id="test_video"></video>
+<div id="log_console"></div>
<script src=../../media-resources/media-file.js></script>
-<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
- (Please avoid writing new tests using video-test.js) -->
-<script src=../../media-resources/video-test.js></script>
+<script src="/w3c/resources/testharness.js"></script>
+<script src="/w3c/resources/testharnessreport.js"></script>
<script>
+async_test(t => {
+ let video = document.getElementById('test_video');
+ let log_console = document.getElementById('log_console');
- var timeupdateCount = 0;
- var waitingCount = 0;
+ // For debugging.
+ function logEvent(e) {
+ let span = document.createElement("span");
+ span.innerHTML = 'event: ' + e.type + '<br>';
+ log_console.appendChild(span);
+ };
- waitForEvent('durationchange');
- waitForEvent('loadedmetadata');
- waitForEvent('loadeddata');
- waitForEvent('canplaythrough');
- waitForEvent('canplay', function () {
+ playback_ew = new EventWatcher(t, video, [
+ 'canplay',
+ 'canplaythrough',
+ 'durationchange',
+ 'loadedmetadata',
+ 'loadeddata',
+ 'play',
+ 'playing',
+ 'waiting']);
- mediaElement.addEventListener('timeupdate', function () {
- // timeupdate events are fired as playback progresses so only verify that at least one
- // event is fired
- ++timeupdateCount;
- if (timeupdateCount == 1)
- consoleWrite("EVENT(timeupdate)");
- } );
+ // The stalled event needs a separate watcher as it can be fired at any
+ // point during the sequence of other playback events. Stalled is triggered
+ // by prolonged network inactivity.
+ stalled_ew = new EventWatcher(t, video, [
+ 'stalled']);
- waitForEvent('waiting', function () {
- ++waitingCount;
- if (waitingCount > 1)
- failTest("too many 'waiting' events fired.");
+ // This helper is an alternative to EventWatcher for events that fire on a
+ // recurring basis. EventWatcher is not suitable because you must always be
+ // "waiting" for the event to fire every time, whereas this method allows
+ // you to just verify that it fired once and move on.
+ function waitForRecurringEvent(name) {
+ let resolve_cb;
+ let promise = new Promise(function(resolve, reject) {
+ resolve_cb = resolve;
+ });
+ video.addEventListener(name, t.step_func((evt) => resolve_cb(evt)));
+ return promise;
+ }
- waitForEvent('timeupdate');
- } );
+ // NOTE: Event sequence verification is achieved by chaining together
+ // promises via then(). To verify separate parallel event sequences (e.g.
+ // playback vs network), we setup separate chains of promises. Promise.all
+ // ensures that all separate sequences complete.
+
+ // Verify playback progresses then runs out of data.
+ Promise.all([
+ // First wait for the resource to load.
+ playback_ew.wait_for('durationchange').then(logEvent)
+ .then(() => playback_ew.wait_for('loadedmetadata')).then(logEvent)
+ .then(() => playback_ew.wait_for('loadeddata')).then(logEvent)
+ .then(() => playback_ew.wait_for('canplay')).then(logEvent)
+ .then(() => playback_ew.wait_for('canplaythrough')).then(logEvent)
+ .then(t.step_func(function() {
+ assert_true(video.readyState > HTMLMediaElement.HAVE_CURRENT_DATA);
+ }))
+ // Now play the file and wait for playback to stall (fire waiting).
+ .then(t.step_func(function() {
+ video.play();
+ // NOTE: setting the wait_for here because we will miss it if we do
+ // it after the play call resolves its promise.
+ return playback_ew.wait_for('play').then(logEvent);
+ }))
+ .then(() => playback_ew.wait_for('playing')).then(logEvent)
+ // Now observe waiting event and verify readyState
+ .then(() => playback_ew.wait_for('waiting')).then(logEvent)
+ .then(t.step_func(function(){
+ assert_equals(HTMLMediaElement.HAVE_CURRENT_DATA, video.readyState);
+ })),
+
+ // timeupdate should fire throughout playback. Make sure we see one.
+ waitForRecurringEvent('timeupdate').then(logEvent),
+
+ // progress should fire throughout download. Make sure we see one.
+ // Later the download should stall.
+ waitForRecurringEvent('progress').then(logEvent)
+ .then(() => stalled_ew.wait_for('stalled')).then(logEvent)
+
+ // Verify download and playback resume.
+ ]).then(() => Promise.all([
+ // Playback should resume when download again makes progress.
+ waitForRecurringEvent('progress').then(logEvent),
+
+ // timeupdate should fire throughout playback. Make sure we see one.
+ waitForRecurringEvent('timeupdate').then(logEvent),
+
+ // Verify correct sequence of playback events.
+ playback_ew.wait_for('canplay').then(logEvent)
+ .then(t.step_func(function() {
+ assert_true(video.readyState > HTMLMediaElement.HAVE_CURRENT_DATA);
+ }))
+ .then(() => playback_ew.wait_for('playing')).then(logEvent)
+ .then(() => playback_ew.wait_for('canplaythrough')).then(logEvent)
+ ])).then(t.step_func_done());
- waitForEventAndEnd('stalled');
- } );
// Find a supported media file.
var mediaFile = findMediaFile("video", "content/test");
var mimeType = mimeTypeForFile(mediaFile);
+ // URL will load part of the file, pause for 8 seconds, then load the rest.
+ // The delay of 8 seconds is chosen to reduce flakiness in waiting for the
+ // stalled event, which should arrive after roughly 3 seconds of inactivity.
+ video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=8";
- video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=6";
- run("video.play()");
+}, "Stalled download pauses playback. When download resumes playback continues. Verify events and readyStates.");
</script>

Powered by Google App Engine
This is Rietveld 408576698