aquilescanta 0ddd3c2bd0 Implement DecryptableSampleQueueReader.isReady
PiperOrigin-RevId: 254746146
2019-07-02 17:43:00 +01:00

278 lines
7.7 KiB
JavaScript

/**
* Copyright (C) 2018 The Android Open Source Project
*
* 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.
*
* @fileoverview Mocks for testing cast components.
*/
goog.module('exoplayer.cast.test.mocks');
goog.setTestOnly();
const NetworkingEngine = goog.require('shaka.net.NetworkingEngine');
let mockState;
let manifest;
/**
* Initializes the state of the mocks. Needs to be called in the setUp method of
* the unit test.
*/
const setUp = function() {
mockState = {
outputMessages: {},
listeners: {},
loadedUri: null,
preferredTextLanguage: '',
preferredAudioLanguage: '',
configuration: null,
responseFilter: null,
isSilent: false,
customMessageListener: undefined,
mediaElementState: {
removedAttributes: [],
},
manifestState: {
isLive: false,
windowDuration: 20,
startTime: 0,
delay: 10,
},
getManifest: () => manifest,
setManifest: (m) => {
manifest = m;
},
shakaError: {
severity: /** CRITICAL */ 2,
code: /** not 7000 (LOAD_INTERUPTED) */ 3,
category: /** any */ 1,
},
simulateLoad: simulateLoadSuccess,
/** @type {function(boolean)} */
setShakaThrowsOnLoad: (doThrow) => {
mockState.simulateLoad = doThrow ? throwShakaError : simulateLoadSuccess;
},
simulateUnload: simulateUnloadSuccess,
/** @type {function(boolean)} */
setShakaThrowsOnUnload: (doThrow) => {
mockState.simulateUnload =
doThrow ? throwShakaError : simulateUnloadSuccess;
},
onSenderConnected: undefined,
onSenderDisconnected: undefined,
};
manifest = {
periods: [{startTime: mockState.manifestState.startTime}],
presentationTimeline: {
getDuration: () => mockState.manifestState.windowDuration,
isLive: () => mockState.manifestState.isLive,
getSegmentAvailabilityStart: () => 0,
getSegmentAvailabilityEnd: () => mockState.manifestState.windowDuration,
getSeekRangeStart: () => 0,
getSeekRangeEnd: () => mockState.manifestState.windowDuration -
mockState.manifestState.delay,
},
};
};
/**
* Simulates a successful `shakaPlayer.load` call.
*
* @param {string} uri The uri to load.
*/
const simulateLoadSuccess = (uri) => {
mockState.loadedUri = uri;
notifyListeners('streaming');
};
/** Simulates a successful `shakaPlayer.unload` call. */
const simulateUnloadSuccess = () => {
mockState.loadedUri = undefined;
notifyListeners('unloading');
};
/** @throws {!ShakaError} Thrown in any case. */
const throwShakaError = () => {
throw mockState.shakaError;
};
/**
* Adds a fake event listener.
*
* @param {string} type The type of the listener.
* @param {function(!Object)} listener The callback listener.
*/
const addEventListener = function(type, listener) {
mockState.listeners[type] = mockState.listeners[type] || [];
mockState.listeners[type].push(listener);
};
/**
* Notifies the fake listeners of the given type.
*
* @param {string} type The type of the listener to notify.
*/
const notifyListeners = function(type) {
if (mockState.isSilent || !mockState.listeners[type]) {
return;
}
for (let i = 0; i < mockState.listeners[type].length; i++) {
mockState.listeners[type][i]({
type: type
});
}
};
/**
* Creates an observable for which listeners can be added.
*
* @return {!Object} An observable object.
*/
const createObservable = () => {
return {
addEventListener: (type, listener) => {
addEventListener(type, listener);
},
};
};
/**
* Creates a fake for the shaka player.
*
* @return {!shaka.Player} A shaka player mock object.
*/
const createShakaFake = () => {
const shakaFake = /** @type {!shaka.Player} */(createObservable());
const mediaElement = createMediaElementFake();
/**
* @return {!HTMLMediaElement} A media element.
*/
shakaFake.getMediaElement = () => mediaElement;
shakaFake.getAudioLanguages = () => [];
shakaFake.getVariantTracks = () => [];
shakaFake.configure = (configuration) => {
mockState.configuration = configuration;
return true;
};
shakaFake.selectTextLanguage = (language) => {
mockState.preferredTextLanguage = language;
};
shakaFake.selectAudioLanguage = (language) => {
mockState.preferredAudioLanguage = language;
};
shakaFake.getManifest = () => manifest;
shakaFake.unload = async () => mockState.simulateUnload();
shakaFake.load = async (uri) => mockState.simulateLoad(uri);
shakaFake.getNetworkingEngine = () => {
return /** @type {!NetworkingEngine} */ ({
registerResponseFilter: (responseFilter) => {
mockState.responseFilter = responseFilter;
},
unregisterResponseFilter: (responseFilter) => {
if (mockState.responseFilter !== responseFilter) {
throw new Error('unregistering invalid response filter');
} else {
mockState.responseFilter = null;
}
},
});
};
return shakaFake;
};
/**
* Creates a fake for a media element.
*
* @return {!HTMLMediaElement} A media element fake.
*/
const createMediaElementFake = () => {
const mediaElementFake = /** @type {!HTMLMediaElement} */(createObservable());
mediaElementFake.load = () => {
// Do nothing.
};
mediaElementFake.play = () => {
mediaElementFake.paused = false;
notifyListeners('playing');
return Promise.resolve();
};
mediaElementFake.pause = () => {
mediaElementFake.paused = true;
notifyListeners('pause');
};
mediaElementFake.seekable = /** @type {!TimeRanges} */({
length: 1,
start: (index) => mockState.manifestState.startTime,
end: (index) => mockState.manifestState.windowDuration,
});
mediaElementFake.removeAttribute = (name) => {
mockState.mediaElementState.removedAttributes.push(name);
if (name === 'src') {
mockState.loadedUri = null;
}
};
mediaElementFake.hasAttribute = (name) => {
return name === 'src' && !!mockState.loadedUri;
};
mediaElementFake.buffered = /** @type {!TimeRanges} */ ({
length: 0,
start: (index) => null,
end: (index) => null,
});
mediaElementFake.paused = true;
return mediaElementFake;
};
/**
* Creates a cast receiver manager fake.
*
* @return {!Object} A cast receiver manager fake.
*/
const createCastReceiverContextFake = () => {
return {
addCustomMessageListener: (namespace, listener) => {
mockState.customMessageListener = listener;
},
sendCustomMessage: (namespace, senderId, message) => {
mockState.outputMessages[senderId] =
mockState.outputMessages[senderId] || [];
mockState.outputMessages[senderId].push(message);
},
addEventListener: (eventName, listener) => {
switch (eventName) {
case 'sender_connected':
mockState.onSenderConnected = listener;
break;
case 'sender_disconnected':
mockState.onSenderDisconnected = listener;
break;
}
},
getSenders: () => [{id: 'sender0'}],
start: () => {},
};
};
/**
* Returns the state of the mocks.
*
* @return {?Object}
*/
const state = () => mockState;
exports.createCastReceiverContextFake = createCastReceiverContextFake;
exports.createShakaFake = createShakaFake;
exports.notifyListeners = notifyListeners;
exports.setUp = setUp;
exports.state = state;