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..cbabed9d297c8f14b63eaf6a1b76979893c75b82 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,115 @@ |
| -<video></video> |
| +<video id="test_video"></video> |
|
wolenetz
2016/07/07 21:32:03
{linux,win}_chromium_rel_ng bots didn't pass this
chcunningham
2016/07/07 22:29:41
The failure is:
17:12:24.365 252 worker/0 http/te
chcunningham
2016/07/12 00:47:17
I've changed the console.log calls to instead log
wolenetz
2016/07/13 22:27:54
Acknowledged.
|
| <p>Test that stalled, timeupdate and waiting events are sent when media load stalls in the middle.</p> |
| <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 => { |
|
wolenetz
2016/07/07 21:32:03
nit: left justify 0-margin the outermost portion o
wolenetz
2016/07/07 21:32:03
nit: is the => {... consistent with other tests? W
chcunningham
2016/07/12 00:47:17
Done.
chcunningham
2016/07/12 00:47:18
I think you mean async_test(function(t) { ... }).
wolenetz
2016/07/13 22:27:54
Acknowledged.
|
| + let video = document.getElementById('test_video'); |
| - var timeupdateCount = 0; |
| - var waitingCount = 0; |
| + // For debugging. |
| + function logEvent(e) { console.log('event fired:' + e.type); }; |
| - waitForEvent('durationchange'); |
| - waitForEvent('loadedmetadata'); |
| - waitForEvent('loadeddata'); |
| - waitForEvent('canplaythrough'); |
| - waitForEvent('canplay', function () { |
| + let ReadyState = { |
|
wolenetz
2016/07/07 21:32:03
These are already exposed on the IDL for HTMLMedia
chcunningham
2016/07/12 00:47:18
Duh! Done.
|
| + HAVE_NOTHING: 0, |
| + HAVE_METADATA: 1, |
| + HAVE_CURRENT_DATA: 2, |
| + HAVE_FUTURE_DATA: 3, |
| + HAVE_ENOUGH_DATA: 4 |
| + } |
| - 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)"); |
| - } ); |
| + playback_ew = new EventWatcher(t, video, [ |
| + 'canplay', |
| + 'canplaythrough', |
| + 'durationchange', |
| + 'loadedmetadata', |
| + 'loadeddata', |
| + 'play', |
| + 'playing', |
| + 'waiting']); |
| - waitForEvent('waiting', function () { |
| - ++waitingCount; |
| - if (waitingCount > 1) |
| - failTest("too many 'waiting' events fired."); |
| + // 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('timeupdate'); |
| - } ); |
| + // 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; |
| + } |
| - waitForEventAndEnd('stalled'); |
| - } ); |
| + // 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. |
| - // Find a supported media file. |
| - var mediaFile = findMediaFile("video", "content/test"); |
| - var mimeType = mimeTypeForFile(mediaFile); |
| + // 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) |
| + .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 > ReadyState.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(ReadyState.HAVE_CURRENT_DATA, video.readyState); |
| + })), |
| - 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()"); |
| + // 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 > ReadyState.HAVE_CURRENT_DATA); |
| + })) |
| + .then(() => playback_ew.wait_for('playing')).then(logEvent) |
| + .then(() => playback_ew.wait_for('canplaythrough')).then(logEvent) |
| + ])).then(t.step_func_done()); |
| + |
| + |
| + // 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 |
| + // 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=6"; |
| + |
| + }, "Stalled download pauses playback. When download resumes playback continues. Verify events and readyStates."); |
| </script> |