| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Test AudioContext.close() |
| </title> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| <script src="../resources/audit-util.js"></script> |
| <script src="../resources/audit.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| let context; |
| let destination; |
| let offline; |
| let osc; |
| let gain; |
| let offlinePromise; |
| let wave = new Float32Array(5); |
| |
| let audit = Audit.createTaskRunner(); |
| |
| // Task: test online context (1). |
| audit.define( |
| { |
| label: 'test-online-context-1', |
| description: 'Test online context 1' |
| }, |
| function(task, should) { |
| // Create a context and verify that the various states are correct |
| // and that close() exists. |
| should( |
| () => context = new AudioContext(), |
| 'context0 = new AudioContext()') |
| .notThrow(); |
| should(context.state, 'context0.state').beEqualTo('running'); |
| |
| // Create gain and oscillator for testing later. |
| should( |
| () => osc = context.createOscillator(), |
| 'osc = context.createOscillator()') |
| .notThrow(); |
| should( |
| () => gain = context.createGain(), |
| 'gain = context0.createGain()') |
| .notThrow(); |
| destination = context.destination; |
| should( |
| () => gain.connect(context.destination), |
| 'gain.connect(context0.destination)') |
| .notThrow(); |
| |
| // Close the context. When the promise is resolved, continue the |
| // next test task. |
| let promise = context.close().then(() => { |
| should( |
| () => gain.disconnect(destination), |
| 'gain.disconnect(destination) after close') |
| .notThrow(); |
| }); |
| should(promise, 'context0.close()') |
| .beResolved() |
| .then(task.done.bind(this)); |
| }); |
| |
| // Task: test online context (2). |
| audit.define( |
| { |
| label: 'test-online-context-2', |
| description: 'Test closed online context 2' |
| }, |
| function(task, should) { |
| // Context is closed, so verify that we cannot create any more |
| // nodes, nor connect any. |
| should(() => context.createAnalyser(), 'context.createAnalyser()') |
| .notThrow(); |
| should( |
| () => context.createConstantSource(), |
| 'context.createConstantSource()') |
| .notThrow(); |
| should( |
| () => context.createBiquadFilter(), |
| 'context.createBiquadFilter()') |
| .notThrow(); |
| |
| // createBuffer is an exception because it's not really tied in any |
| // way to an audio context. And it's useful to be able to create a |
| // buffer inside the oncomplete event of an offline context to use |
| // for testing purposes. |
| should( |
| () => context.createBuffer(1, 1, 48000), |
| 'context.createBuffer(1, 1, 48000)') |
| .notThrow(); |
| |
| should( |
| () => context.createBufferSource(), |
| 'context.createBufferSource()') |
| .notThrow(); |
| should( |
| () => context.createChannelMerger(), |
| 'context.createChannelMerger()') |
| .notThrow(); |
| should( |
| () => context.createChannelSplitter(), |
| 'context.createChannelSplitter()') |
| .notThrow(); |
| should(() => context.createConvolver(), 'context.createConvolver()') |
| .notThrow(); |
| should(() => context.createDelay(), 'context.createDelay()') |
| .notThrow(); |
| should( |
| () => context.createDynamicsCompressor(), |
| 'context.createDynamicsCompressor()') |
| .notThrow(); |
| should(() => context.createGain(), 'context.createGain()') |
| .notThrow(); |
| should( |
| () => context.createIIRFilter([1], [1, .9]), |
| 'context.createIIRFilter()') |
| .notThrow(); |
| should( |
| () => context.createOscillator(), 'context.createOscillator()') |
| .notThrow(); |
| should(() => context.createPanner(), 'context.createPanner()') |
| .notThrow(); |
| should( |
| () => context.createPeriodicWave(wave, wave), |
| 'context.createPeriodicWave(wave, wave)') |
| .notThrow(); |
| should( |
| () => context.createScriptProcessor(), |
| 'context.createScriptProcessor()') |
| .notThrow(); |
| should( |
| () => context.createStereoPanner(), |
| 'context.createStereoPanner()') |
| .notThrow(); |
| should( |
| () => context.createWaveShaper(), 'context.createWaveShaper()') |
| .notThrow(); |
| |
| should(() => osc.connect(gain), 'osc.connect(gain)').notThrow(); |
| should(() => gain.disconnect(), 'gain.disconnect()').notThrow(); |
| |
| // Can't resume a context that is closed (released). |
| should(context.resume(), 'context.resume()') |
| .beRejected() |
| .then(task.done.bind(task)); |
| }); |
| |
| // Task: test online context (3). |
| audit.define( |
| { |
| label: 'test-online-context-3', |
| description: 'Close an online context again' |
| }, |
| function(task, should) { |
| // Try closing the context again. The promise should be rejected. |
| should(context.close(), 'context.close() again') |
| .beRejected() |
| .then(() => { |
| // Finally, run GC. The context should be gone, but this seems |
| // difficult to verify. |
| if (window.gc) |
| gc(); |
| should(context.destination, 'context.destination') |
| .notBeEqualTo(null); |
| }) |
| .then(task.done.bind(task)); |
| }); |
| |
| // Task: test online context (4). |
| audit.define( |
| { |
| label: 'test-online-context-4', |
| description: 'Test closed online context 4' |
| }, |
| function(task, should) { |
| // Create a context and verify that its sampleRate and baseLatency |
| // return valid values whether it's open or closed. |
| should( |
| () => context = new AudioContext(), |
| 'context1 = new AudioContext()') |
| .notThrow(); |
| should(context.sampleRate, 'context1.sampleRate') |
| .beGreaterThan('0'); |
| should(context.sampleRate, 'context1.baseLatency') |
| .beGreaterThan('0'); |
| |
| should(context.close(), 'context1.close()') |
| .beResolved() |
| .then(() => { |
| should(context.sampleRate, 'After close, context1.sampleRate') |
| .beGreaterThan('0'); |
| should( |
| context.sampleRate, 'After close, context1.baseLatency') |
| .beGreaterThan('0'); |
| }) |
| .then(task.done.bind(task)); |
| }); |
| |
| // Task: test offline context (1). |
| audit.define( |
| { |
| label: 'test-offline-context-1', |
| description: 'Test offline context' |
| }, |
| function(task, should) { |
| // For an offline context, verify that close is not defined. |
| should( |
| () => offline = new OfflineAudioContext(1, 1000, 48000), |
| 'offline = new OfflineAudioContext(1, 1000, 48000)') |
| .notThrow(); |
| should(offline.state, 'offline.state').beEqualTo('suspended'); |
| should(offline.close, 'offline.close').beEqualTo(undefined); |
| task.done(); |
| }); |
| |
| audit.run(); |
| </script> |
| </body> |
| </html> |