Files
shaka-player/spec/content_database_spec.js
T
Joey Parrish 4cc4e96dbd Overhaul license comments and file annotations
* Updates all Copyright years to 2015.
* Adds licenses annotations to all JS.
* Makes all licenses identical to avoid repeated appearance in the
  compiled output.
* Drops fileoverview annotations, which do not affect docs output.
* The linter still requires fileoverview on externs.

This patch required a newer closure compiler, since the previous
version we used had a bug regarding license annotations that caused
the license comment block to appear in the output once per file
regardless of uniqueness.

Change-Id: I2e9272db680cba7ecc4613d97f1d3a94ac2244cc
2015-09-08 12:02:34 -07:00

405 lines
13 KiB
JavaScript

/**
* @license
* Copyright 2015 Google Inc.
*
* 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.
*/
goog.require('shaka.media.SegmentIndex');
goog.require('shaka.media.SegmentReference');
goog.require('shaka.media.StreamInfo');
goog.require('shaka.player.DrmSchemeInfo');
goog.require('shaka.util.ContentDatabase');
goog.require('shaka.util.ContentDatabaseReader');
goog.require('shaka.util.ContentDatabaseWriter');
goog.require('shaka.util.PublicPromise');
describe('ContentDatabase', function() {
var fakeIndexSource, fakeInitSource;
var reader, writer, p, testIndex, testReferences, streamInfo;
var originalTimeout, originalFailoverUri, originalName;
const url = 'http://example.com';
const mime = 'video/phony';
const codecs = 'phony';
const duration = 100;
const testInitData = new ArrayBuffer(1024);
const keySystem = 'test.widevine.com';
const licenseServerUrl = 'www.licenseServer.com';
const expectedReferences = [
{ start_time: 0, end_time: 2 },
{ start_time: 2, end_time: 4 },
{ start_time: 4, end_time: null }
];
const drmScheme = new shaka.player.DrmSchemeInfo(
keySystem, licenseServerUrl, false, null);
var customMatchers = {
toMatchReference: function(util) {
return {
compare: function(actual, expected) {
var result = {};
result.pass =
util.equals(actual.start_time, expected.start_time) &&
util.equals(actual.end_time, expected.end_time) &&
actual.url.toString().match(/idb\:\/\/.+\/.+/);
return result;
}
};
}
};
beforeAll(function() {
jasmine.addMatchers(customMatchers);
// Change the timeout.
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; // ms
// Set up mock FailoverUri.
originalFailoverUri = shaka.util.FailoverUri;
var mockFailoverUri = function(callback, url, startByte, endByte) {
return {
fetch: function() {
return Promise.resolve(new ArrayBuffer(768 * 1024));
}
};
};
shaka.util.FailoverUri = mockFailoverUri;
testReferences = [
new shaka.media.SegmentReference(0, 1, createFailover(url, 0, 5)),
new shaka.media.SegmentReference(1, 2, createFailover(url, 6, 9)),
new shaka.media.SegmentReference(2, 3, createFailover(url, 10, 15)),
new shaka.media.SegmentReference(3, 4, createFailover(url, 16, 19)),
new shaka.media.SegmentReference(4, null, createFailover(url, 20, null))
];
testIndex = new shaka.media.SegmentIndex(testReferences);
// Use a database name which will not affect the test app.
originalName = shaka.util.ContentDatabase.DB_NAME;
shaka.util.ContentDatabase.DB_NAME += '_test';
// Start each test run with a clean slate.
(new shaka.util.ContentDatabase('readwrite', null)).deleteDatabase();
fakeIndexSource = {
destroy: function() {},
create: function() { return Promise.resolve(testIndex); }
};
fakeInitSource = {
destroy: function() {},
create: function() { return Promise.resolve(testInitData); }
};
});
beforeEach(function() {
reader = new shaka.util.ContentDatabaseReader();
writer = new shaka.util.ContentDatabaseWriter(null, null);
p = reader.setUpDatabase().then(
function() {
return writer.setUpDatabase();
});
streamInfo = new shaka.media.StreamInfo();
streamInfo.mimeType = mime;
streamInfo.codecs = codecs;
streamInfo.segmentIndexSource = fakeIndexSource;
streamInfo.segmentInitSource = fakeInitSource;
});
afterEach(function() {
reader.closeDatabaseConnection();
writer.closeDatabaseConnection();
});
afterAll(function() {
// Restore the timeout.
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
// Restore FailoverUri.
shaka.util.FailoverUri = originalFailoverUri;
// Restore DB name.
shaka.util.ContentDatabase.DB_NAME = originalName;
});
it('deletes the database', function(done) {
p.then(function() {
reader.closeDatabaseConnection();
return writer.deleteDatabase();
}).then(function() {
var p = new shaka.util.PublicPromise();
var request = window.indexedDB.open(shaka.util.ContentDatabase.DB_NAME);
// onupgradeneeded is only called if the database does not already exist.
request.onupgradeneeded = function(e) {
// Cancel the creation of a new database.
e.target.transaction.abort();
p.resolve(true);
};
request.onsuccess = function() { p.resolve(false); };
request.onerror = function(e) { p.reject(request.error); };
return p;
}).then(function(isDatabaseDeleted) {
expect(isDatabaseDeleted).toBe(true);
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('stores a stream and retrieves its index', function(done) {
p.then(function() {
return writer.insertStream_(
streamInfo, testIndex, testInitData, testReferences.length, 0);
}).then(function(streamId) {
return reader.retrieveStreamIndex(streamId);
}).then(function(streamIndex) {
expect(streamIndex.references[0]).toMatchReference(expectedReferences[0]);
expect(streamIndex.references[1]).toMatchReference(expectedReferences[1]);
expect(streamIndex.references[2]).toMatchReference(expectedReferences[2]);
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('stores a stream with a single segment and retrieves its index',
function(done) {
var references = [
new shaka.media.SegmentReference(0, null, createFailover(url, 6))
];
var index = new shaka.media.SegmentIndex(references);
streamInfo.segmentIndexSource = {
create: function() { return Promise.resolve(index); }
};
p.then(function() {
return writer.insertStream_(streamInfo, index, testInitData, 1, 0);
}).then(function(streamId) {
return reader.retrieveStreamIndex(streamId);
}).then(function(streamIndex) {
expect(streamIndex.references[0]).toMatchReference(
{ start_time: 0, end_time: null });
expect(streamIndex.codecs).toEqual(codecs);
expect(streamIndex.mime_type).toEqual(mime);
expect(streamIndex.init_segment).toEqual(testInitData);
done();
}).catch(function(err) {
fail(err);
done();
});
});
// Bug #157:
it('stores a stream with an explicit end time', function(done) {
var references = [
new shaka.media.SegmentReference(0, 100, createFailover(url))
];
var index = new shaka.media.SegmentIndex(references);
streamInfo.segmentIndexSource = {
create: function() { return Promise.resolve(index); }
};
p.then(function() {
return writer.insertStream_(streamInfo, index, testInitData, 1, 0);
}).then(function(streamId) {
return reader.retrieveStreamIndex(streamId);
}).then(function(streamIndex) {
expect(streamIndex.references.length).toEqual(1);
expect(streamIndex.references[0]).toMatchReference(
{ start_time: 0, end_time: 100 });
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('throws an error when trying to store an invalid stream', function(done) {
p.then(function() {
return writer.insertStream_(null, null, null, 0, 0);
}).then(function() {
fail();
done();
}).catch(function(err) {
expect(err).not.toBeNull();
done();
});
});
it('deletes a stream index and throws error on retrieval', function(done) {
var streamId;
p.then(function() {
return writer.insertStream_(
streamInfo, testIndex, testInitData, testReferences.length, 0);
}).then(function(data) {
streamId = data;
return writer.deleteStream_(streamId);
}).then(function() {
return reader.retrieveStreamIndex(streamId);
}).then(function(streamIndex) {
fail();
done();
}).catch(function(err) {
expect(err.type).toEqual('storage');
done();
});
});
it('retrieves a segment', function(done) {
p.then(function() {
return writer.insertStream_(
streamInfo, testIndex, testInitData, testReferences.length, 0);
}).then(function(streamId) {
return reader.retrieveSegment(streamId, 0);
}).then(function(data) {
expect(data).not.toBeUndefined();
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('throws an error when non-existent segment requested', function(done) {
p.then(function() {
return reader.retrieveSegment(-1, -1);
}).then(function(streamIndex) {
fail();
done();
}).catch(function(err) {
expect(err.type).toEqual('storage');
done();
});
});
it('stores and retrieves a group information', function(done) {
p.then(function() {
return writer.insertGroup(
[streamInfo], ['ABCD', 'EFG'], duration, drmScheme);
}).then(function(groupId) {
return reader.retrieveGroup(groupId);
}).then(function(groupInformation) {
expect(groupInformation.group_id).toEqual(jasmine.any(Number));
expect(groupInformation.stream_ids.length).toEqual(1);
expect(groupInformation.session_ids).toEqual(['ABCD', 'EFG']);
expect(groupInformation.duration).toEqual(duration);
expect(groupInformation.key_system).toEqual(keySystem);
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('retrieves a list of the stored group IDs', function(done) {
var initalGroupIdsLength = 0;
p.then(function() {
return reader.retrieveGroupIds();
}).then(function(groupIds) {
initalGroupIdsLength = groupIds.length;
return writer.insertGroup([streamInfo], ['HIJK'], duration, drmScheme);
}).then(function() {
return reader.retrieveGroupIds();
}).then(function(groupIds) {
expect(groupIds.length - initalGroupIdsLength).toBe(1);
done();
}).catch(function(err) {
fail(err);
done();
});
});
it('deletes group information and throws error on retrieval', function(done) {
var groupId;
p.then(function() {
return writer.insertGroup([streamInfo], [], duration, drmScheme);
}).then(function(resultingGroupId) {
groupId = resultingGroupId;
return writer.deleteGroup(groupId);
}).then(function() {
return reader.retrieveGroup(groupId);
}).then(function(groupInformation) {
fail();
done();
}).catch(function(err) {
expect(err.type).toEqual('storage');
done();
});
});
it('deletes streams in group and throws error on retrieval', function(done) {
var streamIds, groupId;
p.then(function() {
return writer.insertGroup([streamInfo], [], duration, drmScheme);
}).then(function(id) {
groupId = id;
return reader.retrieveGroup(groupId);
}).then(function(data) {
streamIds = data['stream_ids'];
return writer.deleteGroup(groupId);
}).then(function() {
return reader.retrieveStreamIndex(streamIds[0]);
}).then(function(streamIndex) {
fail();
done();
}).catch(function(err) {
expect(err.type).toEqual('storage');
done();
});
});
it('converts old format of data to new format', function(done) {
var streamId, groupId;
p.then(function() {
return writer.insertGroup([streamInfo], [], duration, drmScheme);
}).then(function(currentGroupId) {
groupId = currentGroupId;
return reader.retrieveGroup(currentGroupId);
}).then(function(groupInfo) {
var p = shaka.util.PublicPromise();
delete groupInfo.duration;
delete groupInfo.key_system;
streamId = groupInfo.stream_ids[0];
var groupStore = writer.getGroupStore();
var request = groupStore.put(groupInfo);
request.onsuccess = function() { p.resolve(); };
request.onerror = function(e) { p.reject(request.error); };
return p;
}).then(function() {
return reader.retrieveStreamIndex(streamId);
}).then(function(streamIndex) {
var p = shaka.util.PublicPromise();
streamIndex.duration = 25;
streamIndex.key_system = 'test.key.system';
var indexStore = writer.getIndexStore();
var request = indexStore.put(streamIndex);
request.onsuccess = function() { p.resolve(); };
request.onerror = function(e) { p.reject(request.error); };
return p;
}).then(function() {
return reader.retrieveGroup(groupId);
}).then(function(groupInfo) {
expect(groupInfo.duration).toEqual(25);
expect(groupInfo.key_system).toEqual('test.key.system');
done();
}).catch(function(err) {
fail(err);
done();
});
});
});