2 // Set the testharness.js timeout to 120 seconds so that it is higher than
3 // the LayoutTest timeout. This prevents testharness.js from prematurely
4 // terminating tests and allows the LayoutTest runner to control when to
6 // FIXME: Change this to use explicit_timeout instead once /resources/testharness.js
7 // is updated to a more recent version.
8 setup({ timeout: 120000 });
10 EventExpectationsManager = function(test)
13 this.eventTargetList_ = [];
14 this.waitCallbacks_ = [];
17 EventExpectationsManager.prototype.expectEvent = function(object, eventName, description)
19 var eventInfo = { 'target': object, 'type': eventName, 'description': description};
20 var expectations = this.getExpectations_(object);
21 expectations.push(eventInfo);
24 var waitHandler = this.test_.step_func(function() { t.handleWaitCallback_(); });
25 var eventHandler = this.test_.step_func(function(event)
27 object.removeEventListener(eventName, eventHandler);
28 var expected = expectations[0];
29 assert_equals(event.target, expected.target, "Event target match.");
30 assert_equals(event.type, expected.type, "Event types match.");
31 assert_equals(eventInfo.description, expected.description, "Descriptions match for '" + event.type + "'.");
33 expectations.shift(1);
34 if (t.waitCallbacks_.length > 0)
35 setTimeout(waitHandler, 0);
37 object.addEventListener(eventName, eventHandler);
40 EventExpectationsManager.prototype.waitForExpectedEvents = function(callback)
42 this.waitCallbacks_.push(callback);
43 setTimeout(this.handleWaitCallback_.bind(this), 0);
46 EventExpectationsManager.prototype.expectingEvents = function()
48 for (var i = 0; i < this.eventTargetList_.length; ++i) {
49 if (this.eventTargetList_[i].expectations.length > 0) {
56 EventExpectationsManager.prototype.handleWaitCallback_ = function()
58 if (this.waitCallbacks_.length == 0 || this.expectingEvents())
60 var callback = this.waitCallbacks_.shift(1);
64 EventExpectationsManager.prototype.getExpectations_ = function(target)
66 for (var i = 0; i < this.eventTargetList_.length; ++i) {
67 var info = this.eventTargetList_[i];
68 if (info.target == target) {
69 return info.expectations;
72 var expectations = [];
73 this.eventTargetList_.push({ 'target': target, 'expectations': expectations });
77 function loadData_(test, url, callback, isBinary)
79 var request = new XMLHttpRequest();
80 request.open("GET", url, true);
82 request.responseType = 'arraybuffer';
84 request.onload = test.step_func(function(event)
86 if (request.status != 200) {
87 assert_unreached("Unexpected status code : " + request.status);
90 var response = request.response;
92 response = new Uint8Array(response);
96 request.onerror = test.step_func(function(event)
98 assert_unreached("Unexpected error");
103 function openMediaSource_(test, mediaTag, callback)
105 var mediaSource = new MediaSource();
106 var mediaSourceURL = URL.createObjectURL(mediaSource);
108 var eventHandler = test.step_func(onSourceOpen);
109 function onSourceOpen(event)
111 mediaSource.removeEventListener('sourceopen', eventHandler);
112 URL.revokeObjectURL(mediaSourceURL);
113 callback(mediaSource);
116 mediaSource.addEventListener('sourceopen', eventHandler);
117 mediaTag.src = mediaSourceURL;
120 var MediaSourceUtil = {};
122 MediaSourceUtil.loadTextData = function(test, url, callback)
124 loadData_(test, url, callback, false);
127 MediaSourceUtil.loadBinaryData = function(test, url, callback)
129 loadData_(test, url, callback, true);
132 MediaSourceUtil.fetchManifestAndData = function(test, manifestFilename, callback)
134 var baseURL = '/media/resources/media-source/';
135 var manifestURL = baseURL + manifestFilename;
136 MediaSourceUtil.loadTextData(test, manifestURL, function(manifestText)
138 var manifest = JSON.parse(manifestText);
140 assert_true(MediaSource.isTypeSupported(manifest.type), manifest.type + " is supported.");
142 var mediaURL = baseURL + manifest.url;
143 MediaSourceUtil.loadBinaryData(test, mediaURL, function(mediaData)
145 callback(manifest.type, mediaData);
150 MediaSourceUtil.extractSegmentData = function(mediaData, info)
152 var start = info.offset;
153 var end = start + info.size;
154 return mediaData.subarray(start, end);
157 MediaSourceUtil.getMediaDataForPlaybackTime = function(mediaData, segmentInfo, playbackTimeToAdd)
159 assert_less_than_equal(playbackTimeToAdd, segmentInfo.duration);
160 var mediaInfo = segmentInfo.media;
161 var start = mediaInfo[0].offset;
163 var segmentIndex = 0;
164 while (segmentIndex < mediaInfo.length && mediaInfo[segmentIndex].timecode <= playbackTimeToAdd)
166 numBytes += mediaInfo[segmentIndex].size;
169 return mediaData.subarray(start, numBytes + start);
172 function getFirstSupportedType(typeList)
174 for (var i = 0; i < typeList.length; ++i) {
175 if (MediaSource.isTypeSupported(typeList[i]))
181 var audioOnlyTypes = ['audio/webm;codecs="vorbis"', 'audio/mp4;codecs="mp4a.40.2"'];
182 var videoOnlyTypes = ['video/webm;codecs="vp8"', 'video/mp4;codecs="avc1.4D4001"'];
183 var audioVideoTypes = ['video/webm;codecs="vp8,vorbis"', 'video/mp4;codecs="mp4a.40.2"'];
184 MediaSourceUtil.AUDIO_ONLY_TYPE = getFirstSupportedType(audioOnlyTypes);
185 MediaSourceUtil.VIDEO_ONLY_TYPE = getFirstSupportedType(videoOnlyTypes);
186 MediaSourceUtil.AUDIO_VIDEO_TYPE = getFirstSupportedType(audioVideoTypes);
188 // TODO: Add wrapper object to MediaSourceUtil that binds loaded mediaData to its
189 // associated segmentInfo.
191 function addExtraTestMethods(test)
193 test.failOnEvent = function(object, eventName)
195 object.addEventListener(eventName, test.step_func(function(event)
197 assert_unreached("Unexpected event '" + eventName + "'");
201 test.endOnEvent = function(object, eventName)
203 object.addEventListener(eventName, test.step_func(function(event) { test.done(); }));
206 test.eventExpectations_ = new EventExpectationsManager(test);
207 test.expectEvent = function(object, eventName, description)
209 test.eventExpectations_.expectEvent(object, eventName, description);
212 test.waitForExpectedEvents = function(callback)
214 test.eventExpectations_.waitForExpectedEvents(callback);
217 test.waitForCurrentTimeChange = function(mediaElement, callback)
219 var initialTime = mediaElement.currentTime;
221 var onTimeUpdate = test.step_func(function()
223 if (mediaElement.currentTime != initialTime) {
224 mediaElement.removeEventListener('timeupdate', onTimeUpdate);
229 mediaElement.addEventListener('timeupdate', onTimeUpdate);
232 var oldTestDone = test.done.bind(test);
233 test.done = function()
235 if (test.status == test.PASS) {
236 assert_false(test.eventExpectations_.expectingEvents(), "No pending event expectations.");
242 window['MediaSourceUtil'] = MediaSourceUtil;
243 window['media_test'] = function(testFunction, description, options)
245 options = options || {};
246 return async_test(function(test)
248 addExtraTestMethods(test);
250 }, description, options);
252 window['mediasource_test'] = function(testFunction, description, options)
254 return media_test(function(test)
256 var mediaTag = document.createElement("video");
257 document.body.appendChild(mediaTag);
259 // Overload done() so that element added to the document can be removed.
260 test.removeMediaElement_ = true;
261 var oldTestDone = test.done.bind(test);
262 test.done = function()
264 if (test.removeMediaElement_) {
265 document.body.removeChild(mediaTag);
266 test.removeMediaElement_ = false;
271 openMediaSource_(test, mediaTag, function(mediaSource)
273 testFunction(test, mediaTag, mediaSource);
275 }, description, options);
278 window['mediasource_testafterdataloaded'] = function(testFunction, description, options)
280 mediasource_test(function(test, mediaElement, mediaSource)
282 var segmentInfo = WebMSegmentInfo.testWebM;
283 test.failOnEvent(mediaElement, 'error');
285 var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
286 MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
288 testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData);
290 }, description, options);
293 function timeRangesToString(ranges)
296 for (var i = 0; i < ranges.length; ++i) {
297 s += " [" + ranges.start(i).toFixed(3) + ", " + ranges.end(i).toFixed(3) + ")";
302 window['assertBufferedEquals'] = function(obj, expected, description)
304 var actual = timeRangesToString(obj.buffered);
305 assert_equals(actual, expected, description);