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' |
); |