From 6b0996f752d400d94b57722ec6a55f7c858b997f Mon Sep 17 00:00:00 2001 From: Kyu Simm Date: Thu, 19 Dec 2019 13:26:50 -0800 Subject: [PATCH] Reject an unresolved promise when canceling CreateSDPTask --- src/task/CreateSDPTask.ts | 22 +++++++++++++++++++++- test/task/CreateSDPTask.test.ts | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/task/CreateSDPTask.ts b/src/task/CreateSDPTask.ts index e9447e09b2..430132bf79 100644 --- a/src/task/CreateSDPTask.ts +++ b/src/task/CreateSDPTask.ts @@ -10,10 +10,17 @@ import BaseTask from './BaseTask'; export default class CreateSDPTask extends BaseTask { protected taskName = 'CreateSDPTask'; + private cancelPromise: (error: Error) => void; + constructor(private context: AudioVideoControllerState) { super(context.logger); } + cancel(): void { + const error = new Error(`canceling ${this.name()}`); + this.cancelPromise && this.cancelPromise(error); + } + sessionUsesAudio(): boolean { return true; } @@ -35,7 +42,20 @@ export default class CreateSDPTask extends BaseTask { offerToReceiveVideo: this.sessionUsesVideo(), }; this.logger.info(`offerOptions: ${JSON.stringify(offerOptions)}`); - this.context.sdpOfferInit = await this.context.peer.createOffer(offerOptions); + + await new Promise(async (resolve, reject) => { + this.cancelPromise = (error: Error) => { + reject(error); + }; + + try { + this.context.sdpOfferInit = await this.context.peer.createOffer(offerOptions); + resolve(); + } catch (error) { + reject(error); + } + }); + this.context.logger.info(`created offer ${JSON.stringify(this.context.sdpOfferInit)}`); } } diff --git a/test/task/CreateSDPTask.test.ts b/test/task/CreateSDPTask.test.ts index 6ba7efb390..22fbe8fcae 100644 --- a/test/task/CreateSDPTask.test.ts +++ b/test/task/CreateSDPTask.test.ts @@ -5,19 +5,23 @@ import * as chai from 'chai'; import AudioVideoControllerState from '../../src/audiovideocontroller/AudioVideoControllerState'; import NoOpAudioVideoController from '../../src/audiovideocontroller/NoOpAudioVideoController'; +import TimeoutScheduler from '../../src/scheduler/TimeoutScheduler'; import CreateSDPTask from '../../src/task/CreateSDPTask'; import Task from '../../src/task/Task'; import DefaultVideoStreamIdSet from '../../src/videostreamidset/DefaultVideoStreamIdSet'; +import DOMMockBehavior from '../dommock/DOMMockBehavior'; import DOMMockBuilder from '../dommock/DOMMockBuilder'; describe('CreateSDPTask', () => { const expect: Chai.ExpectStatic = chai.expect; let context: AudioVideoControllerState; - let domMockBuilder: DOMMockBuilder | null = null; + let domMockBuilder: DOMMockBuilder; + let domMockBehavior: DOMMockBehavior; let task: Task; beforeEach(() => { - domMockBuilder = new DOMMockBuilder(); + domMockBehavior = new DOMMockBehavior(); + domMockBuilder = new DOMMockBuilder(domMockBehavior); context = new AudioVideoControllerState(); context.audioVideoController = new NoOpAudioVideoController(); context.videoTileController = context.audioVideoController.videoTileController; @@ -79,4 +83,29 @@ describe('CreateSDPTask', () => { task.run().catch(() => done()); }); }); + + describe('cancel', () => { + it('cancels a task when the session is timed out', done => { + let called = false; + + domMockBehavior.asyncWaitMs = 500; + new TimeoutScheduler(50).start(() => { + task.cancel(); + }); + + task + .run() + .then(() => { + done(new Error('This line should not be reached.')); + }) + .catch(() => { + called = true; + }); + + new TimeoutScheduler(domMockBehavior.asyncWaitMs + 50).start(() => { + expect(called).to.be.true; + done(); + }); + }); + }); });