Chromium Code Reviews| 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..272c8235f859dca96fdec2b0a172f95f81af9401 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 progress 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) |
|
wolenetz
2016/07/13 22:27:54
nit: hard to read. please indent.
chcunningham
2016/07/14 22:25:01
Done.
|
| + .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 6 seconds, then load the rest. |
| + // The delay of 6 seconds is chosen to reduce flakiness in waiting for the |
|
wolenetz
2016/07/13 22:27:54
This lengthy test therefore will need to be added
wolenetz
2016/07/14 18:56:43
Oops. This test is already listed in SlowTests (ht
|
| + // 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"; |
|
wolenetz
2016/07/13 22:27:54
Which is desired? 6 or 8 (fix the comments, above,
chcunningham
2016/07/14 22:25:01
Fixed the comment. I cranked it to 8 because the s
|
| - 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> |