| Index: LayoutTests/webaudio/audiocontext-suspend-resume.html
|
| diff --git a/LayoutTests/webaudio/audiocontext-suspend-resume.html b/LayoutTests/webaudio/audiocontext-suspend-resume.html
|
| index 56a7f133b21ed9515e1480a44f8ecfffab995aaf..8c16380b9a6cc867460b063fafd397231b770ddd 100644
|
| --- a/LayoutTests/webaudio/audiocontext-suspend-resume.html
|
| +++ b/LayoutTests/webaudio/audiocontext-suspend-resume.html
|
| @@ -9,44 +9,128 @@
|
|
|
| <body>
|
| <script>
|
| - description("Test suspend/resume for an AudioContext");
|
| + description("Test suspend/resume for an (offline) AudioContext");
|
| window.jsTestIsAsync = true;
|
|
|
| - var context = new AudioContext();
|
| + var offlineContext;
|
| + var osc;
|
| + var p1;
|
| + var p2;
|
| + var p3;
|
| +
|
| + var sampleRate = 44100;
|
| + var durationInSeconds = 1;
|
|
|
| var audit = Audit.createTaskRunner();
|
|
|
| - // Task: check the method interface.
|
| - audit.defineTask('interface', function (done) {
|
| - Should('typeof context.suspend()', typeof context.suspend).beEqualTo('function');
|
| - Should('typeof context.resume()', typeof context.resume).beEqualTo('function');
|
| - done();
|
| + // Convenience function that returns a function that calls the |passFailFunc|
|
| + // with the given |message|. The |passFailFunc| should be either |testPassed|
|
| + // or |testFailed|.
|
| + function handlePromise(passFailFunc, message) {
|
| + return function () {
|
| + passFailFunc(message);
|
| + };
|
| + }
|
| +
|
| + // Task: test suspend().
|
| + audit.defineTask('test-suspend', function (done) {
|
| +
|
| + // Test suspend/resume. Ideally this test is best with a online
|
| + // AudioContext, but content shell doesn't really have a working online
|
| + // AudioContext. Hence, use an OfflineAudioContext. Not all possible
|
| + // scenarios can be easily checked with an offline context instead of an
|
| + // online context.
|
| +
|
| + // Create an audio context with an oscillator.
|
| + shouldNotThrow("offlineContext = new OfflineAudioContext(1, durationInSeconds * sampleRate, sampleRate)");
|
| + osc = offlineContext.createOscillator();
|
| + osc.connect(offlineContext.destination);
|
| +
|
| + // Verify the state.
|
| + shouldBeEqualToString("offlineContext.state", "suspended");
|
| +
|
| + // Multiple calls to suspend() should not be a problem. But we can't test
|
| + // that on an offline context. Thus, check that suspend() on an
|
| + // OfflineAudioContext rejects the promise.
|
| + shouldNotThrow("p1 = offlineContext.suspend()");
|
| + shouldBeType("p1", "Promise");
|
| + p1.then(
|
| + handlePromise(testFailed, "offlineContext.suspend() should have been rejected for an offline context"),
|
| + function (e) {
|
| + if (e.name === "InvalidAccessError") {
|
| + testPassed(
|
| + "offlineContext.suspend() was correctly rejected: " + e);
|
| + } else {
|
| + testFailed(
|
| + "offlineContext.suspend() was correctly rejected but expected InvalidAccessError, not: " + e);
|
| + }
|
| + }
|
| + ).then(done);
|
| });
|
|
|
| - // Task: check the promise resolution.
|
| - audit.defineTask('promise-resolution', function (done) {
|
| - Should('context.suspend()', context.suspend()).beResolved().then(done);
|
|
|
| - // Resuming the context cannot be tested with the trybot or the Content
|
| - // Shell because it requires the physical audio device to run.
|
| + // Task: test resume().
|
| + audit.defineTask('test-resume', function (done) {
|
| +
|
| + // Multiple calls to resume should not be a problem. But we can't test
|
| + // that on an offline context. Thus, check that resume() on an
|
| + // OfflineAudioContext rejects the promise.
|
| + shouldNotThrow("p2 = offlineContext.resume()");
|
| + shouldBeType("p2", "Promise");
|
| +
|
| + // Resume doesn't actually resume an offline context
|
| + shouldBeEqualToString("offlineContext.state", "suspended");
|
| + p2.then(
|
| + handlePromise(testFailed, "offlineContext.resume() should have been rejected for an offline context"),
|
| + function (e) {
|
| + if (e.name === "InvalidAccessError") {
|
| + testPassed(
|
| + "offlineContext.resume() was correctly rejected: " + e);
|
| + } else {
|
| + testFailed(
|
| + "offlineContext.resume() was correctly rejected but expected InvalidAccessError, not: " + e);
|
| + }
|
| + }
|
| + ).then(done);
|
| });
|
|
|
| - // Task: test corner cases.
|
| - audit.defineTask('corner-cases', function (done) {
|
| + // Task: test the state after context closed.
|
| + audit.defineTask('test-after-close', function (done) {
|
|
|
| - Should('Calling multiple context.suspend()', function() {
|
| - context.suspend();
|
| - context.suspend();
|
| - }).notThrow();
|
| + // Render the offline context.
|
| + osc.start();
|
|
|
| - context.close().then(function () {
|
| - Should('Calling context.suspend() after close()', context.suspend())
|
| - .beRejected();
|
| + // Test suspend/resume in tested promise pattern. We don't care about the
|
| + // actual result of the offline rendering.
|
| + shouldNotThrow("p3 = offlineContext.startRendering()");
|
| + p3.then(function () {
|
| + shouldBeEqualToString("offlineContext.state", "closed");
|
|
|
| - Should('Calling context.resume() after close()', context.resume())
|
| - .beRejected().then(done);
|
| + // suspend() should be rejected on a closed context.
|
| + offlineContext.suspend().then(
|
| + handlePromise(testFailed, "offlineContext.suspend() on a closed context not rejected"),
|
| + function (e) {
|
| + if (e.name === "InvalidAccessError") {
|
| + testPassed("offlineContext.suspend() on a closed context rejected: " + e);
|
| + } else {
|
| + testFailed("offlineContext.suspend() on a closed context rejected but expected InvalidAccessError, not: " + e);
|
| + }
|
| + }
|
| + ).then(function () {
|
| + // resume() should be rejected on closed context.
|
| + offlineContext.resume().then(
|
| + handlePromise(testFailed, "offlineContext.resume() on a closed context not rejected"),
|
| + function (e) {
|
| + if (e.name === "InvalidAccessError") {
|
| + testPassed("offlineContext.resume() on a closed context rejected: " + e);
|
| + } else {
|
| + testFailed("offlineContext.resume() on a closed context rejected but expected InvalidAccessError, not: " + e);
|
| + }
|
| + }
|
| + ).then(done);
|
| + });
|
| +
|
| });
|
| -
|
| });
|
|
|
| audit.defineTask('finish-test', function (done) {
|
| @@ -55,9 +139,9 @@
|
| });
|
|
|
| audit.runTasks(
|
| - 'interface',
|
| - 'promise-resolution',
|
| - 'corner-cases',
|
| + 'test-suspend',
|
| + 'test-resume',
|
| + 'test-after-close',
|
| 'finish-test'
|
| );
|
|
|
|
|