Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
zangue committed Mar 7, 2023
1 parent 26c6644 commit 1a4f919
Show file tree
Hide file tree
Showing 5 changed files with 588 additions and 249 deletions.
1 change: 1 addition & 0 deletions test/media/streaming_engine_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ describe('StreamingEngine', () => {
onInitSegmentAppended: () => {},
beforeAppendSegment: () => Promise.resolve(),
onMetadata: () => {},
disableStream: (stream, time) => false,
};
streamingEngine = new shaka.media.StreamingEngine(
/** @type {shaka.extern.Manifest} */(manifest), playerInterface);
Expand Down
234 changes: 233 additions & 1 deletion test/media/streaming_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ describe('StreamingEngine', () => {
let beforeAppendSegment;
/** @type {!jasmine.Spy} */
let onMetadata;
/** @type {!jasmine.Spy} */
let disableStream;

/** @type {function(function(), number)} */
let realSetTimeout;
Expand Down Expand Up @@ -437,6 +439,8 @@ describe('StreamingEngine', () => {
onMetadata = jasmine.createSpy('onMetadata');
getBandwidthEstimate = jasmine.createSpy('getBandwidthEstimate');
getBandwidthEstimate.and.returnValue(1e3);
disableStream = jasmine.createSpy('disableStream');
disableStream.and.callFake(() => false);

beforeAppendSegment.and.callFake((segment) => {
return Promise.resolve();
Expand All @@ -447,6 +451,7 @@ describe('StreamingEngine', () => {
config.rebufferingGoal = 2;
config.bufferingGoal = 5;
config.bufferBehind = Infinity;
config.maxDisabledTime = 0; // Do not disable stream by default
}

goog.asserts.assert(
Expand All @@ -465,6 +470,7 @@ describe('StreamingEngine', () => {
onInitSegmentAppended: () => {},
beforeAppendSegment: Util.spyFunc(beforeAppendSegment),
onMetadata: Util.spyFunc(onMetadata),
disableStream: Util.spyFunc(disableStream),
};
streamingEngine = new shaka.media.StreamingEngine(
/** @type {shaka.extern.Manifest} */(manifest), playerInterface);
Expand Down Expand Up @@ -2171,6 +2177,195 @@ describe('StreamingEngine', () => {
// baseDelay == 10000, maybe be longer due to delays in the event loop.
expect(callbackTime - startTime).toBeGreaterThanOrEqual(10000);
});

it('temporarily disables stream if configured to do so', async () => {
setupVod();

const targetUri = '0_video_0';

failRequestsForTarget(netEngine, targetUri);

mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.maxDisabledTime = 2;
createStreamingEngine(config);

spyOn(streamingEngine, 'makeAbortDecision_').and.callFake(() => {
return Promise.resolve();
});

onError.and.callFake((error) => {
expect(error.severity).toBe(shaka.util.Error.Severity.RECOVERABLE);
expect(error.category).toBe(shaka.util.Error.Category.NETWORK);
expect(error.code).toBe(shaka.util.Error.Code.BAD_HTTP_STATUS);
});

disableStream.and.callFake((stream, time) => {
expect(stream).toBe(variant.video);
expect(time).toBeGreaterThan(0);

createAlternateSegmentIndex(stream, alternateVideoStream);

streamingEngine.switchVariant(
alternateVariant, /* clearBuffer= */ true,
/* safeMargin= */ 0, /* force= */ true);
return true;
});

// Here we go!
streamingEngine.switchVariant(variant);
streamingEngine.switchTextStream(textStream);
await streamingEngine.start();
playing = true;

await runTest();
expect(disableStream).toHaveBeenCalledTimes(1);
});

it('does not temporarily disables stream if not configured to',
async () => {
setupVod();

const targetUri = '0_audio_init';
failRequestsForTarget(
netEngine, targetUri, shaka.util.Error.Code.HTTP_ERROR);

mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
const config =
shaka.util.PlayerConfiguration.createDefault().streaming;
config.maxDisabledTime = 0; // Do not disable streams.
createStreamingEngine(config);

onError.and.callFake((error) => {
expect(error.code).toBe(shaka.util.Error.Code.HTTP_ERROR);
});

// Here we go!
streamingEngine.switchVariant(variant);
streamingEngine.switchTextStream(textStream);
await streamingEngine.start();
playing = true;

await runTest();
expect(disableStream).not.toHaveBeenCalled();
});

it('always tries to recover shaka.util.Error.Code.SEGMENT_MISSING',
async () => {
setupVod();

const targetUri = '0_video_0';
failRequestsForTarget(
netEngine, targetUri, shaka.util.Error.Code.SEGMENT_MISSING);

mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
const config =
shaka.util.PlayerConfiguration.createDefault().streaming;
config.maxDisabledTime = 0; // Do not disable streams.
createStreamingEngine(config);

spyOn(streamingEngine, 'makeAbortDecision_').and.callFake(() => {
return Promise.resolve();
});

onError.and.callFake((error) => {
expect(error.severity).toBe(shaka.util.Error.Severity.RECOVERABLE);
expect(error.category).toBe(shaka.util.Error.Category.NETWORK);
expect(error.code).toBe(shaka.util.Error.Code.SEGMENT_MISSING);
});

disableStream.and.callFake((stream, time) => {
expect(stream).toBe(variant.video);
expect(time).toBeGreaterThan(0);

createAlternateSegmentIndex(stream, alternateVideoStream);

streamingEngine.switchVariant(
alternateVariant, /* clearBuffer= */ true,
/* safeMargin= */ 0, /* force= */ true);
return true;
});

// Here we go!
streamingEngine.switchVariant(variant);
streamingEngine.switchTextStream(textStream);
await streamingEngine.start();
playing = true;

await runTest();
expect(disableStream).toHaveBeenCalledTimes(1);
});

it('throws recoverable error if try to disable stream succeeded',
async () => {
setupVod();

const targetUri = '0_video_init';
failRequestsForTarget(
netEngine, targetUri, shaka.util.Error.Code.BAD_HTTP_STATUS);

mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
const config =
shaka.util.PlayerConfiguration.createDefault().streaming;
config.maxDisabledTime = 2;
createStreamingEngine(config);

disableStream.and.callFake(() => true);

onError.and.callFake((error) => {
expect(error).toEqual(jasmine.objectContaining({
code: shaka.util.Error.Code.BAD_HTTP_STATUS,
category: shaka.util.Error.Category.NETWORK,
severity: shaka.util.Error.Severity.RECOVERABLE,
handled: true,
}));
});

// Here we go!
streamingEngine.switchVariant(variant);
streamingEngine.switchTextStream(textStream);
await streamingEngine.start();
playing = true;

await runTest();
expect(disableStream).toHaveBeenCalled();
expect(onError).toHaveBeenCalled();
});

it('throws critical error if try to disable stream failed', async () => {
setupVod();

const targetUri = '0_video_init';
failRequestsForTarget(
netEngine, targetUri, shaka.util.Error.Code.BAD_HTTP_STATUS);

mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.maxDisabledTime = 2;
createStreamingEngine(config);

disableStream.and.callFake(() => false);

onError.and.callFake((error) => {
expect(error).toEqual(jasmine.objectContaining({
code: shaka.util.Error.Code.BAD_HTTP_STATUS,
category: shaka.util.Error.Category.NETWORK,
severity: shaka.util.Error.Severity.CRITICAL,
handled: false,
}));
});

// Here we go!
streamingEngine.switchVariant(variant);
streamingEngine.switchTextStream(textStream);
await streamingEngine.start();
playing = true;

await runTest();

expect(disableStream).toHaveBeenCalled();
expect(onError).toHaveBeenCalled();
});
});

describe('retry()', () => {
Expand Down Expand Up @@ -3875,7 +4070,8 @@ describe('StreamingEngine', () => {
if (request.uris[0] == targetUri) {
const data = [targetUri];

if (errorCode == shaka.util.Error.Code.BAD_HTTP_STATUS) {
if (errorCode == shaka.util.Error.Code.BAD_HTTP_STATUS ||
errorCode == shaka.util.Error.Code.SEGMENT_MISSING) {
data.push(404);
data.push('');
}
Expand Down Expand Up @@ -3946,4 +4142,40 @@ describe('StreamingEngine', () => {
return segmentReference;
};
}

/**
* Create a valid segment index for |alternateStream| based on |baseStream|
* segment index.
*
* @param {shaka.extern.Stream} baseStream
* @param {shaka.extern.Stream} alternateStream
*/
function createAlternateSegmentIndex(baseStream, alternateStream) {
const createSegmentIndexSpy =
Util.funcSpy(alternateStream.createSegmentIndex);
const altSegmentIndex = new shaka.test.FakeSegmentIndex();

altSegmentIndex.find.and.callFake(
(time) => baseStream.segmentIndex.find(time));

altSegmentIndex.get.and.callFake((pos) => {
const ref = baseStream.segmentIndex.get(pos);

if (ref) {
const altInitUri = ref.initSegmentReference.getUris()[0] + '_alt';
const altSegmentUri = ref.getUris()[0] + '_alt';

ref.initSegmentReference.getUris = () => [altInitUri];
ref.getUris = () => [altSegmentUri];
return ref;
}

return null;
});

createSegmentIndexSpy.and.callFake(() => {
alternateStream.segmentIndex = altSegmentIndex;
return Promise.resolve();
});
}
});
Loading

0 comments on commit 1a4f919

Please sign in to comment.