shaka-player
Version:
DASH/EME video player library
292 lines (257 loc) • 9.65 kB
JavaScript
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
describe('CmcdManager', () => {
const CmcdManager = shaka.util.CmcdManager;
const uuidRegex =
'[A-F\\d]{8}-[A-F\\d]{4}-4[A-F\\d]{3}-[89AB][A-F\\d]{3}-[A-F\\d]{12}';
const data = {
'sid': 'c936730c-031e-4a73-976f-92bc34039c60',
'cid': 'xyz',
'su': false,
'nor': '../testing/3.m4v',
'nrr': '0-99',
'd': 6066.66,
'mtp': 10049,
'bs': true,
'br': 52317,
'v': 1,
'pr': 1,
'com.test-hello': 'world',
'com.test-testing': 1234,
'com.test-exists': true,
'com.test-notExists': false,
'com.test-token': Symbol('s'),
};
describe('Query serialization', () => {
it('produces correctly serialized data', () => {
const query = CmcdManager.toQuery(data);
const result = 'br=52317,bs,cid="xyz",com.test-exists,' +
'com.test-hello="world",com.test-testing=1234,' +
'com.test-token=s,d=6067,mtp=10000,' +
'nor="..%2Ftesting%2F3.m4v",nrr="0-99",' +
'sid="c936730c-031e-4a73-976f-92bc34039c60"';
expect(query).toBe(result);
});
it('escapes reserve character in string values', () => {
const query = CmcdManager.toQuery({
'com.test-escape': 'Double "Quotes"',
});
const result = 'com.test-escape="Double \\"Quotes\\""';
expect(query).toBe(result);
});
});
describe('Header serialization', () => {
it('produces all header shards', () => {
const header = CmcdManager.toHeaders(data);
expect(header).toEqual({
'CMCD-Object': 'br=52317,d=6067',
'CMCD-Request': 'com.test-exists,com.test-hello="world",' +
'com.test-testing=1234,com.test-token=s,mtp=10000,' +
'nor="..%2Ftesting%2F3.m4v",nrr="0-99"',
'CMCD-Session': 'cid="xyz",sid="c936730c-031e-4a73-976f-92bc34039c60"',
'CMCD-Status': 'bs',
});
});
it('ignores empty shards', () => {
expect(CmcdManager.toHeaders({br: 200})).toEqual({
'CMCD-Object': 'br=200',
});
});
});
describe('CmcdManager instance', () => {
const ObjectUtils = shaka.util.ObjectUtils;
const playerInterface = {
isLive: () => false,
getBandwidthEstimate: () => 10000000,
getBufferedInfo: () => ({
video: [
{start: 0, end: 5},
{start: 6, end: 31.234},
{start: 35, end: 40},
],
}),
getVariantTracks: () => /** @type {Array.<shaka.extern.Track>} */([
{
type: 'variant',
bandwidth: 50000,
videoBandwidth: 40000,
audioBandWidth: 10000,
},
{
type: 'variant',
bandwidth: 5000000,
videoBandwidth: 4000000,
audioBandWidth: 1000000,
},
]),
getPlaybackRate: () => 1,
getCurrentTime: () => 10,
};
const sid = '2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3';
const config = {
enabled: false,
sessionId: '',
contentId: 'testing',
useHeaders: false,
};
/** @type shaka.util.CmcdManager */
let cmcdManager = new CmcdManager(playerInterface, config);
const request = {
uris: ['https://test.com/test.mpd'],
method: 'GET',
body: null,
headers: {
testing: '1234',
},
allowCrossSiteCredentials: false,
retryParameters: /** @type {shaka.extern.RetryParameters} */({}),
licenseRequestType: null,
sessionId: null,
drmInfo: null,
initData: null,
initDataType: null,
streamDataCallback: null,
};
const manifestInfo = {
format: shaka.util.CmcdManager.StreamingFormat.DASH,
};
const segmentInfo = {
type: 'video',
init: false,
duration: 3.33,
mimeType: 'application/mp4',
codecs: 'avc1.42001e',
bandwidth: 5234167,
};
describe('configuration', () => {
it('does not modify requests when disabled', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applyManifestData(r, manifestInfo);
expect(r.uris[0]).toBe(request.uris[0]);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.uris[0]).toBe(request.uris[0]);
});
it('generates a session id if not provided', () => {
config.enabled = true;
cmcdManager = new CmcdManager(playerInterface, config);
const r = ObjectUtils.cloneObject(request);
cmcdManager.applyManifestData(r, manifestInfo);
const regex = new RegExp(`sid%3D%22${uuidRegex}%22`, 'i');
expect(regex.test(r.uris[0])).toBe(true);
});
});
describe('query mode', () => {
beforeAll(() => {
config.sessionId = sid;
cmcdManager = new CmcdManager(playerInterface, config);
});
it('modifies manifest request uris', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applyManifestData(r, manifestInfo);
const uri = 'https://test.com/test.mpd?CMCD=cid%3D%22testing%22%2C' +
'mtp%3D10000%2Cot%3Dm%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
expect(r.uris[0]).toBe(uri);
});
it('modifies segment request uris', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
const uri = 'https://test.com/test.mpd?CMCD=bl%3D21200%2Cbr%3D5234%2Ccid%3D%22' +
'testing%22%2Cd%3D3330%2Cmtp%3D10000%2Cot%3Dv%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Cst%3Dv%2Csu%2C' +
'tb%3D4000';
expect(r.uris[0]).toBe(uri);
});
it('modifies text request uris', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applyTextData(r);
const uri = 'https://test.com/test.mpd?CMCD=cid%3D%22' +
'testing%22%2Cmtp%3D10000%2Cot%3Dc%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
expect(r.uris[0]).toBe(uri);
});
});
describe('header mode', () => {
beforeAll(() => {
config.useHeaders = true;
cmcdManager = new CmcdManager(playerInterface, config);
});
it('modifies manifest request headers', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applyManifestData(r, manifestInfo);
expect(r.headers).toEqual({
'testing': '1234',
'CMCD-Object': 'ot=m',
'CMCD-Request': 'mtp=10000,su',
'CMCD-Session': 'cid="testing",sf=d,' +
'sid="2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3"',
});
});
it('modifies segment request headers', () => {
const r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers).toEqual({
'testing': '1234',
'CMCD-Object': 'br=5234,d=3330,ot=v,tb=4000',
'CMCD-Request': 'bl=21200,mtp=10000,su',
'CMCD-Session': 'cid="testing",sf=d,' +
'sid="2ed2d1cd-970b-48f2-bfb3-50a79e87cfa3",st=v',
});
});
});
describe('src= mode', () => {
it('modifies media stream uris', () => {
const r = cmcdManager
.appendSrcData('https://test.com/test.mp4', 'video/mp4');
const uri = 'https://test.com/test.mp4?CMCD=cid%3D%22testing%22%2C' +
'mtp%3D10000%2Cot%3Dav%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
expect(r).toBe(uri);
});
it('modifies manifest stream uris', () => {
const r = cmcdManager
.appendSrcData('https://test.com/test.m3u8', 'application/x-mpegurl');
const uri = 'https://test.com/test.m3u8?CMCD=cid%3D%22testing%22%2C' +
'mtp%3D10000%2Cot%3Dm%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
expect(r).toBe(uri);
});
it('modifies text track uris', () => {
const r = cmcdManager.appendTextTrackData('https://test.com/test.vtt');
const uri = 'https://test.com/test.vtt?CMCD=cid%3D%22testing%22%2C' +
'mtp%3D10000%2Cot%3Dc%2Csf%3Dd%2C' +
'sid%3D%222ed2d1cd-970b-48f2-bfb3-50a79e87cfa3%22%2Csu';
expect(r).toBe(uri);
});
});
describe('adheres to the spec', () => {
beforeAll(() => {
cmcdManager.setBuffering(false);
cmcdManager.setBuffering(true);
});
it('sends bs only once', () => {
let r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers['CMCD-Status']).toContain('bs');
r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers['CMCD-Status']).not.toContain('bs');
});
it('sends su until buffering is complete', () => {
let r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers['CMCD-Request']).toContain(',su');
r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers['CMCD-Request']).toContain(',su');
cmcdManager.setBuffering(false);
r = ObjectUtils.cloneObject(request);
cmcdManager.applySegmentData(r, segmentInfo);
expect(r.headers['CMCD-Request']).not.toContain(',su');
});
});
});
});