2019/media/progressiveTest.js (372 lines of code) (raw):
/**
* @license
* Copyright 2018 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
/**
* Progressive Test Suite.
* @class
*/
var ProgressiveTest = function() {
var tests = [];
var info = 'Default Timeout: ' + TestBase.timeout + 'ms';
var fields = ['passes', 'failures', 'timeouts'];
var createProgressiveTest = function(category, name, mandatory) {
var t = createTest(name);
t.prototype.category = category;
t.prototype.index = tests.length;
t.prototype.passes = 0;
t.prototype.failures = 0;
t.prototype.timeouts = 0;
t.prototype.mandatory = true;
if (typeof mandatory == 'boolean' && !mandatory)
t.prototype.mandatory = false;
tests.push(t);
return t;
};
/**
* Test the inital state of a video element.
*/
var createInitialMediaStateTest = function(state, value, check) {
var test = createProgressiveTest('state before initial', state);
check = typeof(check) === 'undefined' ? 'checkEq' : check;
test.prototype.title = 'Test if the state ' + state +
' is correct when media element is just created';
test.prototype.start = function(runner, video) {
test.prototype.status = util.formatStatus(util.getAttr(video, state));
runner[check](util.getAttr(video, state), value, state);
runner.succeed();
};
};
createInitialMediaStateTest('src', ''); // can actually be undefined
createInitialMediaStateTest('currentSrc', '');
createInitialMediaStateTest('defaultPlaybackRate', 1);
createInitialMediaStateTest('playbackRate', 1);
createInitialMediaStateTest('duration', NaN);
createInitialMediaStateTest('paused', true);
createInitialMediaStateTest('seeking', false);
createInitialMediaStateTest('ended', false);
createInitialMediaStateTest('videoWidth', 0);
createInitialMediaStateTest('videoHeight', 0);
createInitialMediaStateTest('buffered.length', 0);
createInitialMediaStateTest('played.length', 0);
createInitialMediaStateTest('seekable.length', 0);
createInitialMediaStateTest('networkState', HTMLMediaElement.NETWORK_EMPTY);
createInitialMediaStateTest('readyState', HTMLMediaElement.HAVE_NOTHING);
/**
* Test the state when a src has been assigned to the video element.
*/
var createMediaStateAfterSrcAssignedTest = function(state, value, check) {
var test = createProgressiveTest('state after src assigned', state);
check = typeof(check) === 'undefined' ? 'checkEq' : check;
test.prototype.title = 'Test if the state ' + state +
' is correct when media element is a src has been assigned';
test.prototype.start = function(runner, video) {
video.src = Media.H264.ProgressiveLow.src;
test.prototype.status = util.formatStatus(util.getAttr(video, state));
runner[check](util.getAttr(video, state), value, state);
runner.succeed();
};
};
createMediaStateAfterSrcAssignedTest(
'networkState', HTMLMediaElement.NETWORK_NO_SOURCE);
createMediaStateAfterSrcAssignedTest(
'readyState', HTMLMediaElement.HAVE_NOTHING);
createMediaStateAfterSrcAssignedTest('src', '', 'checkNE');
/**
* Test the state of video element when loadstart event is fired.
*/
var createMediaStateInLoadStart = function(state, value, check) {
var test = createProgressiveTest('state in loadstart', state);
check = typeof(check) === 'undefined' ? 'checkEq' : check;
test.prototype.title = 'Test if the state ' + state +
' is correct when media element is in loadstart';
test.prototype.start = function(runner, video) {
video.addEventListener('loadstart', function() {
test.prototype.status = util.formatStatus(util.getAttr(video, state));
runner[check](util.getAttr(video, state), value, state);
runner.succeed();
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createMediaStateInLoadStart('networkState', HTMLMediaElement.NETWORK_LOADING);
createMediaStateInLoadStart('readyState', HTMLMediaElement.HAVE_NOTHING);
createMediaStateInLoadStart('currentSrc', '', 'checkNE');
/**
* Test if there is progress event.
*/
var createProgressTest = function() {
var test = createProgressiveTest('event', 'onprogress');
test.prototype.title = 'Test if there is progress event.';
test.prototype.start = function(runner, video) {
var self = this;
video.src = Media.H264.ProgressiveLow.src + '?' + Date.now();
video.addEventListener('progress', function() {
self.log('onprogress called');
runner.succeed();
});
};
};
createProgressTest();
/**
* Test timeupdate event of video element.
*/
var createTimeUpdateTest = function() {
var test = createProgressiveTest('event', 'ontimeupdate');
test.prototype.title = 'Test if there is timeupdate event.';
test.prototype.start = function(runner, video) {
var self = this;
video.src = Media.H264.ProgressiveLow.src;
video.addEventListener('timeupdate', function() {
self.log('ontimeupdate called');
runner.succeed();
});
video.play();
};
};
createTimeUpdateTest();
/**
* Test canplay event in video element.
*/
var createCanPlayTest = function() {
var test = createProgressiveTest('event', 'canplay');
test.prototype.title = 'Test if there is canplay event.';
test.prototype.start = function(runner, video) {
var self = this;
video.src = Media.H264.ProgressiveLow.src;
video.addEventListener('canplay', function() {
self.log('canplay called');
runner.succeed();
});
};
};
createCanPlayTest();
/**
* Test the autoplay attribute in video element.
*/
var createAutoPlayTest = function() {
var test = createProgressiveTest('control', 'autoplay');
test.prototype.title = 'Test if autoplay works';
test.prototype.start = function(runner, video) {
var self = this;
video.autoplay = true;
video.src = Media.H264.ProgressiveLow.src;
video.addEventListener('timeupdate', function() {
self.log('ontimeupdate called');
runner.succeed();
});
};
};
createAutoPlayTest();
/**
* Test the network states of video element.
*/
var createNetworkStateTest = function() {
var test = createProgressiveTest('state', 'networkState');
test.prototype.title = 'Test if the network state is correct';
test.prototype.start = function(runner, video) {
var self = this;
runner.checkEq(video.networkState, HTMLMediaElement.NETWORK_EMPTY,
'networkState');
video.addEventListener('suspend', function() {
self.log('onsuspend called');
var networkState = video.networkState;
if (networkState == HTMLMediaElement.NETWORK_LOADING) {
// Skip NETWORK_LOADING state wait until next suspend event to find
// NETWORK_IDLE state.
return;
}
runner.checkEq(networkState, HTMLMediaElement.NETWORK_IDLE,
'networkState');
runner.succeed();
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createNetworkStateTest();
/**
* Test video without valid source data. The video should pause.
*/
var createPlayingWithoutDataPaused = function() {
var test = createProgressiveTest('play without data', 'paused');
test.prototype.title = 'Test if we can play without any data';
test.prototype.start = function(runner, video) {
video.src = 'hang.py';
video.play();
test.prototype.status = util.formatStatus(video.paused);
runner.checkEq(video.paused, false, 'video.paused');
runner.succeed();
};
};
createPlayingWithoutDataPaused();
/**
* Test playing a video without valid source data. Waiting event should occur.
*/
var createPlayingWithoutDataWaiting = function() {
var test = createProgressiveTest('play without data', 'onwaiting');
test.prototype.title = 'Test if we can play without any data';
test.prototype.start = function(runner, video) {
video.addEventListener('waiting', function() {
runner.checkEq(video.currentTime, 0, 'video.currentTime');
runner.succeed();
});
video.src = 'hang.py';
video.play();
};
};
createPlayingWithoutDataWaiting();
/**
* Test the maximum timupdate event granularity for different playbackRate.
* It should be smaller than 0.26.
*/
var createTimeUpdateMaxGranularity = function(playbackRate) {
var test = createProgressiveTest('timeupdate', 'maxGranularityPlaybackRate' +
parseFloat(playbackRate).toFixed(2));
test.prototype.title = 'Test the time update granularity.';
test.prototype.start = function(runner, video) {
var warmUpCount = 15;
var maxGranularity = 0;
var times = 0;
var last = 0;
video.addEventListener('loadstart', function() {
video.playbackRate = playbackRate;
video.play();
video.addEventListener('timeupdate', function() {
if (times >= warmUpCount) {
var interval = Date.now() - last;
if (interval > maxGranularity)
maxGranularity = interval;
}
if (times === 50 + warmUpCount) {
maxGranularity = maxGranularity / 1000.0;
runner.checkLE(maxGranularity, 0.26, 'maxGranularity');
runner.succeed();
}
last = Date.now();
++times;
});
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createTimeUpdateMaxGranularity(0.25);
createTimeUpdateMaxGranularity(0.50);
createTimeUpdateMaxGranularity(1.00);
createTimeUpdateMaxGranularity(1.25);
createTimeUpdateMaxGranularity(1.50);
createTimeUpdateMaxGranularity(2.0);
/**
* Test the minimum timupdate event granularity for different playbackRate.
* It should be larger than 0.015.
*/
var createTimeUpdateMinGranularity = function(playbackRate) {
var test = createProgressiveTest('timeupdate', 'minGranularityPlaybackRate' +
parseFloat(playbackRate).toFixed(2));
test.prototype.title = 'Test the time update granularity.';
test.prototype.start = function(runner, video) {
var warmUpCount = 15;
var minGranularity = Infinity;
var times = 0;
var last = 0;
video.addEventListener('loadstart', function() {
video.playbackRate = playbackRate;
video.play();
video.addEventListener('timeupdate', function() {
if (times >= warmUpCount) {
var interval = Date.now() - last;
if (interval > 1 && interval < minGranularity)
minGranularity = interval;
}
if (times === 50 + warmUpCount) {
minGranularity = minGranularity / 1000.0;
runner.checkGE(minGranularity, 0.015, 'minGranularity');
runner.succeed();
}
last = Date.now();
++times;
});
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createTimeUpdateMinGranularity(0.25);
createTimeUpdateMinGranularity(0.50);
createTimeUpdateMinGranularity(1.00);
createTimeUpdateMinGranularity(1.25);
createTimeUpdateMinGranularity(1.50);
createTimeUpdateMinGranularity(2.0);
/**
* Test the timeupdate accuracy by video.currentTime.
*/
var createTimeUpdateAccuracy = function() {
var test = createProgressiveTest('timeupdate', 'accuracy');
test.prototype.title = 'Test the time update granularity.';
test.prototype.start = function(runner, video) {
var maxTimeDiff = 0;
var baseTimeDiff = 0;
var times = 0;
video.addEventListener('canplaythrough', function() {
video.play();
video.addEventListener('timeupdate', function() {
if (times === 0) {
baseTimeDiff = util.ElapsedTimeInS() - video.currentTime;
} else {
var timeDiff = util.ElapsedTimeInS() - video.currentTime;
maxTimeDiff = Math.max(
Math.abs(timeDiff - baseTimeDiff), maxTimeDiff);
}
if (times > 500 || video.currentTime > 10) {
test.prototype.status = util.Round(maxTimeDiff, 2);
runner.checkLE(maxTimeDiff, 0.25, 'maxTimeDiff');
runner.succeed();
}
++times;
});
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createTimeUpdateAccuracy();
/**
* Test if time updates progress when video is playing.
*/
var createTimeUpdateProgressing = function() {
var test = createProgressiveTest('timeupdate', 'progressing');
test.prototype.title = 'Test if the time updates progress.';
test.prototype.start = function(runner, video) {
var last = 0;
var times = 0;
video.addEventListener('timeupdate', function() {
if (times === 0) {
last = video.currentTime;
} else {
runner.checkGE(video.currentTime, last, 'video.currentTime');
last = video.currentTime;
}
if (video.currentTime > 10) {
test.prototype.status = util.Round(video.currentTime, 2);
runner.succeed();
}
++times;
});
video.src = Media.H264.ProgressiveLow.src;
video.play();
};
};
createTimeUpdateProgressing();
/**
* Test if time updates progress when video is playing with initial seek.
*/
var createTimeUpdateProgressingWithInitialSeek = function() {
var test = createProgressiveTest('timeupdate', 'progressing after seek');
test.prototype.title = 'Test if the time updates progress.';
test.prototype.start = function(runner, video) {
var last = 0;
var times = 0;
video.addEventListener('canplay', function() {
if (times == 0) {
video.currentTime = 0.001;
video.play();
video.addEventListener('timeupdate', function() {
if (times === 0) {
last = video.currentTime;
} else {
runner.checkGE(video.currentTime, last, 'video.currentTime');
last = video.currentTime;
}
if (video.currentTime > 10) {
test.prototype.status = util.Round(video.currentTime, 2);
runner.succeed();
}
++times;
});
}
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createTimeUpdateProgressingWithInitialSeek();
/**
* Test if time updates progress when video is playing with duration check.
*/
var createTimeUpdateProgressingWithDurationCheck = function() {
var test = createProgressiveTest('timeupdate', 'duration on timeupdate');
test.prototype.title = 'Test if the duration is non-negative when time ' +
'updates.';
test.prototype.start = function(runner, video) {
video.addEventListener('timeupdate', function() {
runner.checkGE(video.duration, 0, 'video.duration');
if (video.currentTime > 1) {
runner.succeed();
}
});
video.src = Media.H264.ProgressiveLow.src;
video.play();
};
};
createTimeUpdateProgressingWithDurationCheck();
/**
* Test if video plays at expected playback rate.
*/
var createPlaybackRateTest = function(playbackRate) {
var test = createProgressiveTest('playbackRate', 'PlaybackRate' +
parseFloat(playbackRate).toFixed(2));
test.prototype.title = 'Test playbackRate plays back at the expected rate.';
test.prototype.start = function(runner, video) {
video.addEventListener('loadstart', function() {
video.playbackRate = playbackRate;
video.play();
var warmUpCount = 15;
var times = 0;
var realTimeLast;
var playTimeLast;
video.addEventListener('timeupdate', function() {
if (times <= warmUpCount) {
realTimeLast = Date.now();
playTimeLast = video.currentTime;
} else {
var realTimeNext = Date.now();
var playTimeNext = video.currentTime;
var realTimeDelta = (realTimeNext - realTimeLast) / 1000.0;
var playTimeDelta = playTimeNext - playTimeLast;
runner.checkApproxEq(playTimeDelta, realTimeDelta * playbackRate,
'playback time delta', 0.25);
realTimeLast = realTimeNext;
playTimeLast = playTimeNext;
}
if (times === 50 + warmUpCount) {
runner.succeed();
}
times++;
});
});
video.src = Media.H264.ProgressiveLow.src;
};
};
createPlaybackRateTest(0.25);
createPlaybackRateTest(0.50);
createPlaybackRateTest(1.00);
createPlaybackRateTest(1.25);
createPlaybackRateTest(1.50);
createPlaybackRateTest(2.0);
return {tests: tests, info: info, fields: fields, viewType: 'default'};
};