Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #2956 from Orange-OpenSource/improveUnitTests
Browse files Browse the repository at this point in the history
Improve unit tests
  • Loading branch information
epiclabsDASH committed Mar 18, 2019
2 parents 78e482c + fef4961 commit 2e02049
Show file tree
Hide file tree
Showing 16 changed files with 336 additions and 40 deletions.
6 changes: 4 additions & 2 deletions src/dash/models/DashManifestModel.js
Expand Up @@ -287,7 +287,7 @@ function DashManifestModel() {
}

function getLabelsForAdaptation(adaptation) {
if (!adaptation.Label_asArray || !adaptation.Label_asArray.length) {
if (!adaptation || !adaptation.Label_asArray || !Array.isArray(adaptation.Label_asArray)) {
return [];
}

Expand Down Expand Up @@ -715,7 +715,9 @@ function DashManifestModel() {
if (manifest.hasOwnProperty(DashConstants.AVAILABILITY_START_TIME)) {
mpd.availabilityStartTime = new Date(manifest.availabilityStartTime.getTime());
} else {
mpd.availabilityStartTime = new Date(manifest.loadedTime.getTime());
if (manifest.loadedTime) {
mpd.availabilityStartTime = new Date(manifest.loadedTime.getTime());
}
}

if (manifest.hasOwnProperty(DashConstants.AVAILABILITY_END_TIME)) {
Expand Down
8 changes: 7 additions & 1 deletion src/streaming/rules/abr/BolaRule.js
Expand Up @@ -383,6 +383,13 @@ function BolaRule(config) {
}

function getMaxIndex(rulesContext) {
const switchRequest = SwitchRequest(context).create();

if (!rulesContext || !rulesContext.hasOwnProperty('getMediaInfo') || !rulesContext.hasOwnProperty('getMediaType') ||
!rulesContext.hasOwnProperty('getScheduleController') || !rulesContext.hasOwnProperty('getStreamInfo') ||
!rulesContext.hasOwnProperty('getAbrController') || !rulesContext.hasOwnProperty('useBufferOccupancyABR')) {
return switchRequest;
}
const mediaInfo = rulesContext.getMediaInfo();
const mediaType = rulesContext.getMediaType();
const scheduleController = rulesContext.getScheduleController();
Expand All @@ -392,7 +399,6 @@ function BolaRule(config) {
const streamId = streamInfo ? streamInfo.id : null;
const isDynamic = streamInfo && streamInfo.manifestInfo && streamInfo.manifestInfo.isDynamic;
const useBufferOccupancyABR = rulesContext.useBufferOccupancyABR();
const switchRequest = SwitchRequest(context).create();
switchRequest.reason = switchRequest.reason || {};

if (!useBufferOccupancyABR) {
Expand Down
7 changes: 6 additions & 1 deletion src/streaming/rules/abr/DroppedFramesRule.js
Expand Up @@ -17,6 +17,11 @@ function DroppedFramesRule() {
}

function getMaxIndex(rulesContext) {
const switchRequest = SwitchRequest(context).create();

if (!rulesContext || !rulesContext.hasOwnProperty('getDroppedFramesHistory')) {
return switchRequest;
}
const droppedFramesHistory = rulesContext.getDroppedFramesHistory();
if (droppedFramesHistory) {
const dfh = droppedFramesHistory.getFrameHistory();
Expand All @@ -38,7 +43,7 @@ function DroppedFramesRule() {
return SwitchRequest(context).create(maxIndex, {droppedFrames: droppedFrames});
}

return SwitchRequest(context).create();
return switchRequest;
}

instance = {
Expand Down
27 changes: 14 additions & 13 deletions src/streaming/utils/DOMStorage.js
Expand Up @@ -136,23 +136,24 @@ function DOMStorage(config) {
}

function getSavedMediaSettings(type) {
let mediaSettings = null;

checkConfig();
//Checks local storage to see if there is valid, non-expired media settings
if (!canStore(STORAGE_TYPE_LOCAL, LAST_MEDIA_SETTINGS)) return null;

let mediaSettings = null;
const key = LOCAL_STORAGE_SETTINGS_KEY_TEMPLATE.replace(/\?/, type);
try {
const obj = JSON.parse(localStorage.getItem(key)) || {};
const isExpired = (new Date().getTime() - parseInt(obj.timestamp, 10)) >= settings.get().streaming.lastMediaSettingsCachingInfo.ttl || false;
mediaSettings = obj.settings;
if (canStore(STORAGE_TYPE_LOCAL, LAST_MEDIA_SETTINGS)) {
const key = LOCAL_STORAGE_SETTINGS_KEY_TEMPLATE.replace(/\?/, type);
try {
const obj = JSON.parse(localStorage.getItem(key)) || {};
const isExpired = (new Date().getTime() - parseInt(obj.timestamp, 10)) >= settings.get().streaming.lastMediaSettingsCachingInfo.ttl || false;
mediaSettings = obj.settings;

if (isExpired) {
localStorage.removeItem(key);
mediaSettings = null;
if (isExpired) {
localStorage.removeItem(key);
mediaSettings = null;
}
} catch (e) {
return null;
}
} catch (e) {
return null;
}
return mediaSettings;
}
Expand Down
117 changes: 117 additions & 0 deletions test/unit/dash.models.DashManifestModel.js
@@ -1,4 +1,5 @@
import DashManifestModel from '../../src/dash/models/DashManifestModel';
import DashConstants from '../../src/dash/constants/DashConstants';
import BaseURL from '../../src/dash/vo/BaseURL';

import MpdHelper from './helpers/MPDHelper';
Expand Down Expand Up @@ -39,12 +40,37 @@ describe('DashManifestModel', function () {
expect(suggestedPresentationDelay).to.be.null; // jshint ignore:line
});

it('should return null when getSuggestedPresentationDelay is called and mpd is an empty object', () => {
const suggestedPresentationDelay = dashManifestModel.getSuggestedPresentationDelay({});

expect(suggestedPresentationDelay).to.be.null; // jshint ignore:line
});

it('should return 5 when getSuggestedPresentationDelay is called and mpd is an object with suggestedPresentationDelay attribute', () => {
const suggestedPresentationDelay = dashManifestModel.getSuggestedPresentationDelay({suggestedPresentationDelay: 5});

expect(suggestedPresentationDelay).to.be.equal(5); // jshint ignore:line
});

it('should return null when getAvailabilityStartTime is called and mpd is undefined', () => {
const availabilityStartTime = dashManifestModel.getAvailabilityStartTime();

expect(availabilityStartTime).to.be.null; // jshint ignore:line
});

it('should return null when getAvailabilityStartTime is called and mpd is an empty object', () => {
const availabilityStartTime = dashManifestModel.getAvailabilityStartTime({});

expect(availabilityStartTime).to.be.null; // jshint ignore:line
});

it('should return correct value when getAvailabilityStartTime is called and mpd is object with the availabilityStartTime attribute', () => {
const now = new Date();
const availabilityStartTime = dashManifestModel.getAvailabilityStartTime({availabilityStartTime: now});

expect(availabilityStartTime).to.be.equal(now.getTime()); // jshint ignore:line
});

it('should return false when getUseCalculatedLiveEdgeTimeForAdaptation is called and adaptation is undefined', () => {
const useCalculatedLiveEdge = dashManifestModel.getUseCalculatedLiveEdgeTimeForAdaptation();

Expand Down Expand Up @@ -224,6 +250,18 @@ describe('DashManifestModel', function () {
expect(codec).to.be.null; // jshint ignore:line
});

it('should return correct codec when getCodec is called and representationId is an integer and addResolutionInfo is true', () => {
const codec = dashManifestModel.getCodec({ Representation_asArray: [{mimeType: 'video/mp4', codecs: 'avc1.4D400D', width: 1080, height: 960}] }, 0, true);

expect(codec).to.be.equal('video/mp4;codecs="avc1.4D400D";width="1080";height="960"'); // jshint ignore:line
});

it('should return correct codec when getCodec is called and representationId is an integer and addResolutionInfo is false', () => {
const codec = dashManifestModel.getCodec({ Representation_asArray: [{mimeType: 'video/mp4', codecs: 'avc1.4D400D', width: 1080, height: 960}] }, 0, false);

expect(codec).to.be.equal('video/mp4;codecs="avc1.4D400D"'); // jshint ignore:line
});

it('should return null when getMimeType is called and adaptation is undefined', () => {
const mimeType = dashManifestModel.getMimeType();

Expand All @@ -248,6 +286,48 @@ describe('DashManifestModel', function () {
expect(kid).to.be.null; // jshint ignore:line
});

it('should return kid value when getKID is called and adaptation is well defined', () => {
const kid = dashManifestModel.getKID({'cenc:default_KID': 'testKid'});

expect(kid).to.equal('testKid'); // jshint ignore:line
});

it('should return empty array when getLabelsForAdaptation is called and adaptation is undefined', () => {
const labels = dashManifestModel.getLabelsForAdaptation();

expect(labels).to.be.instanceOf(Array); // jshint ignore:line
expect(labels).to.be.empty; // jshint ignore:line
});

it('should return empty array when getLabelsForAdaptation is called and adaptation is not well defined', () => {
const labels = dashManifestModel.getLabelsForAdaptation({});

expect(labels).to.be.instanceOf(Array); // jshint ignore:line
expect(labels).to.be.empty; // jshint ignore:line
});

it('should return empty array when getLabelsForAdaptation is called and adaptation is not well defined', () => {
const labels = dashManifestModel.getLabelsForAdaptation({Label_asArray: true});

expect(labels).to.be.instanceOf(Array); // jshint ignore:line
expect(labels).to.be.empty; // jshint ignore:line
});

it('should return empty array when getLabelsForAdaptation is called and adaptation is well defined with an empty Label_asArray', () => {
const labels = dashManifestModel.getLabelsForAdaptation({Label_asArray: []});

expect(labels).to.be.instanceOf(Array); // jshint ignore:line
expect(labels).to.be.empty; // jshint ignore:line
});

it('should return correct array when getLabelsForAdaptation is called and adaptation is well defined', () => {
const labels = dashManifestModel.getLabelsForAdaptation({Label_asArray: [{lang: 'fre', __text: 'french'}, {lang: 'eng', __text: 'english'}]});

expect(labels).to.be.instanceOf(Array); // jshint ignore:line
expect(labels.length).to.equal(2); // jshint ignore:line
expect(labels[0].lang).to.equal('fre'); // jshint ignore:line
});

it('should return null when getContentProtectionData is called and adaptation is undefined', () => {
const contentProtection = dashManifestModel.getContentProtectionData();

Expand All @@ -266,6 +346,18 @@ describe('DashManifestModel', function () {
expect(duration).to.equal(Number.MAX_SAFE_INTEGER || Number.MAX_VALUE); // jshint ignore:line
});

it('should return duration when getDuration is called and manifest has a defined mediaPresentationDuration', () => {
const duration = dashManifestModel.getDuration({mediaPresentationDuration: 50});

expect(duration).to.equal(50); // jshint ignore:line
});

it('should return infinity when getDuration is called and manifest is a dynamic one', () => {
const duration = dashManifestModel.getDuration({type: DashConstants.DYNAMIC});

expect(duration).to.equal(Infinity); // jshint ignore:line
});

it('should return 0 when getRepresentationCount is called and adaptation is undefined', () => {
const representationCount = dashManifestModel.getRepresentationCount();

Expand All @@ -278,6 +370,12 @@ describe('DashManifestModel', function () {
expect(bdtw).to.be.NaN; // jshint ignore:line
});

it('should return correct value when getBandwidth is called and representation is defined', () => {
const bdtw = dashManifestModel.getBandwidth({bandwidth: 9600});

expect(bdtw).to.equal(9600); // jshint ignore:line
});

it('should return null when getBitrateListForAdaptation is called and adaptation is undefined', () => {
const bitrateList = dashManifestModel.getBitrateListForAdaptation();

Expand Down Expand Up @@ -317,6 +415,18 @@ describe('DashManifestModel', function () {
expect(location).to.be.undefined; // jshint ignore:line
});

it('should return undefined when getLocation is called and manifest is an empty object', () => {
const location = dashManifestModel.getLocation({});

expect(location).to.be.undefined; // jshint ignore:line
});

it('should return valid location when getLocation is called and manifest is a valid object', () => {
const location = dashManifestModel.getLocation({Location: '', Location_asArray: ['location_1']});

expect(location).to.be.equal('location_1'); // jshint ignore:line
});

it('should return an empty Array when getUTCTimingSources is called and manifest is undefined', () => {
const utcSourceArray = dashManifestModel.getUTCTimingSources();

Expand Down Expand Up @@ -351,6 +461,13 @@ describe('DashManifestModel', function () {
expect(mpd.manifest).to.be.null; // jshint ignore:line
});

it('should return mpd.manifest not null when getMpd is called and manifest is defined', () => {
const mpd = dashManifestModel.getMpd({});

expect(mpd.manifest).not.to.be.null; // jshint ignore:line
expect(mpd.manifest.availabilityStartTime).to.be.undefined; // jshint ignore:line
});

it('should return an error when getRegularPeriods and getEndTimeForLastPeriod are called and duration is undefined', () => {
const manifest = {
'manifest': {
Expand Down
14 changes: 13 additions & 1 deletion test/unit/mocks/RulesContextMock.js
Expand Up @@ -23,7 +23,11 @@ function RulesContextMock () {
return fragRequest;
};
this.getRepresentationInfo = function () {};
this.getAbrController = function () {};
this.getAbrController = function () {
return {
getThroughputHistory: function () {}
};
};
this.getSwitchHistory = function () {
return new switchRequestHistoryMock();
};
Expand All @@ -42,6 +46,14 @@ function RulesContextMock () {
this.useBufferOccupancyABR = function () {

};

this.getDroppedFramesHistory = function () {

};

this.getStreamInfo = function () {

};
}

export default RulesContextMock;
4 changes: 1 addition & 3 deletions test/unit/mss.MssFragmentProcessor.js
@@ -1,5 +1,4 @@
import MssFragmentProcessor from '../../src/mss/MssFragmentProcessor';
import MetricsModel from '../../src/streaming/models/MetricsModel';
import PlaybackController from '../../src/streaming/controllers/PlaybackController';
import EventBus from '../../src/core/EventBus';
import MssErrors from '../../src/mss/errors/MssErrors';
Expand All @@ -14,11 +13,10 @@ const expect = require('chai').expect;
const fs = require('fs');

const context = {};
const metricsModel = MetricsModel(context).getInstance();
const playbackController = PlaybackController(context).getInstance();
const eventBus = EventBus(context).getInstance();
const errorHandlerMock = new ErrorHandlerMock();
const mssFragmentProcessor = MssFragmentProcessor(context).create({metricsModel: metricsModel,
const mssFragmentProcessor = MssFragmentProcessor(context).create({
playbackController: playbackController,
eventBus: eventBus,
ISOBoxer: ISOBoxer,
Expand Down
5 changes: 4 additions & 1 deletion test/unit/streaming.controllers.AbrControllerSpec.js
Expand Up @@ -10,6 +10,7 @@ import DomStorageMock from './mocks/DomStorageMock';
import DashMetricsMock from './mocks/DashMetricsMock';
import AdapterMock from './mocks/AdapterMock';
import MediaPlayerModelMock from './mocks/MediaPlayerModelMock';
import StreamControllerMock from './mocks/StreamControllerMock';

const expect = require('chai').expect;

Expand All @@ -30,6 +31,7 @@ describe('AbrController', function () {
const domStorageMock = new DomStorageMock();
const dashMetricsMock = new DashMetricsMock();
const mediaPlayerModelMock = new MediaPlayerModelMock();
const streamControllerMock = new StreamControllerMock();

beforeEach(function () {
abrCtrl.setConfig({
Expand All @@ -38,7 +40,8 @@ describe('AbrController', function () {
adapter: adapterMock,
domStorage: domStorageMock,
mediaPlayerModel: mediaPlayerModelMock,
settings: settings
settings: settings,
streamController: streamControllerMock
});
abrCtrl.registerStreamType('video', streamProcessor);
});
Expand Down
3 changes: 3 additions & 0 deletions test/unit/streaming.controllers.BufferControllerSpec.js
Expand Up @@ -88,6 +88,9 @@ describe('BufferController', function () {
});

describe('Method createBuffer/getBuffer', function () {
it('should not create a preBufferSink if mediaInfo is undefined', function () {
expect(bufferController.createBuffer()).to.be.null; // jshint ignore:line
});

it('should create a preBufferSink if controller is initialized without a mediaSource', function () {
bufferController.initialize(null);
Expand Down

0 comments on commit 2e02049

Please sign in to comment.