| OLD | NEW |
| 1 <!doctype html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title>Test AudioContext.close()</title> | 4 <title> |
| 5 <script src="../../resources/testharness.js"></script> | 5 Test AudioContext.close() |
| 6 <script src="../../resources/testharnessreport.js"></script> | 6 </title> |
| 7 <script src="../resources/audit-util.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
| 8 <script src="../resources/audit.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
| 9 </head> | 9 <script src="../resources/audit-util.js"></script> |
| 10 | 10 <script src="../resources/audit.js"></script> |
| 11 <body> | 11 </head> |
| 12 <script> | 12 <body> |
| 13 let context; | 13 <script id="layout-test-code"> |
| 14 let destination; | 14 let context; |
| 15 let offline; | 15 let destination; |
| 16 let osc; | 16 let offline; |
| 17 let gain; | 17 let osc; |
| 18 let offlinePromise; | 18 let gain; |
| 19 let wave = new Float32Array(1); | 19 let offlinePromise; |
| 20 | 20 let wave = new Float32Array(1); |
| 21 let audit = Audit.createTaskRunner(); | 21 |
| 22 | 22 let audit = Audit.createTaskRunner(); |
| 23 // Task: test online context (1). | 23 |
| 24 audit.define({ | 24 // Task: test online context (1). |
| 25 label: 'test-online-context-1', | 25 audit.define( |
| 26 description: "Test online context 1" | 26 { |
| 27 }, function (task, should) { | 27 label: 'test-online-context-1', |
| 28 // Create a context and verify that the various states are correct and | 28 description: 'Test online context 1' |
| 29 // that close() exists. | 29 }, |
| 30 should(() => context = new AudioContext(), | 30 function(task, should) { |
| 31 "context0 = new AudioContext()") | 31 // Create a context and verify that the various states are correct |
| 32 .notThrow(); | 32 // and that close() exists. |
| 33 should(context.state, "context0.state") | 33 should( |
| 34 .beEqualTo("running"); | 34 () => context = new AudioContext(), |
| 35 | 35 'context0 = new AudioContext()') |
| 36 // Create gain and oscillator for testing later. | 36 .notThrow(); |
| 37 should(() => osc = context.createOscillator(), | 37 should(context.state, 'context0.state').beEqualTo('running'); |
| 38 "osc = context.createOscillator()") | 38 |
| 39 .notThrow(); | 39 // Create gain and oscillator for testing later. |
| 40 should(() => gain = context.createGain(), | 40 should( |
| 41 "gain = context0.createGain()") | 41 () => osc = context.createOscillator(), |
| 42 .notThrow(); | 42 'osc = context.createOscillator()') |
| 43 destination = context.destination; | 43 .notThrow(); |
| 44 should(() => gain.connect(context.destination), | 44 should( |
| 45 "gain.connect(context0.destination)") | 45 () => gain = context.createGain(), |
| 46 .notThrow(); | 46 'gain = context0.createGain()') |
| 47 | 47 .notThrow(); |
| 48 // Close the context. When the promise is resolved, continue the next | 48 destination = context.destination; |
| 49 // test task. | 49 should( |
| 50 let promise = context.close().then(() => { | 50 () => gain.connect(context.destination), |
| 51 should(() => gain.disconnect(destination), | 51 'gain.connect(context0.destination)') |
| 52 "gain.disconnect(destination) after close") | 52 .notThrow(); |
| 53 .notThrow(); | 53 |
| 54 }); | 54 // Close the context. When the promise is resolved, continue the |
| 55 should(promise, "context0.close()") | 55 // next test task. |
| 56 .beResolved() | 56 let promise = context.close().then(() => { |
| 57 .then(task.done.bind(this)); | 57 should( |
| 58 }); | 58 () => gain.disconnect(destination), |
| 59 | 59 'gain.disconnect(destination) after close') |
| 60 // Task: test online context (2). | 60 .notThrow(); |
| 61 audit.define({ | 61 }); |
| 62 label: 'test-online-context-2', | 62 should(promise, 'context0.close()') |
| 63 description: "Test closed online context 2" | 63 .beResolved() |
| 64 }, function (task, should) { | 64 .then(task.done.bind(this)); |
| 65 // Context is closed, so verify that we cannot create any more nodes, | 65 }); |
| 66 // nor connect any. | 66 |
| 67 should(() => context.createAnalyser(), "context.createAnalyser()") | 67 // Task: test online context (2). |
| 68 .throw("InvalidStateError"); | 68 audit.define( |
| 69 should(() => context.createBiquadFilter(), | 69 { |
| 70 "context.createBiquadFilter()") | 70 label: 'test-online-context-2', |
| 71 .throw("InvalidStateError"); | 71 description: 'Test closed online context 2' |
| 72 | 72 }, |
| 73 // createBuffer is an exception because it's not really tied in any way | 73 function(task, should) { |
| 74 // to an audio context. And it's useful to be able to create a buffer | 74 // Context is closed, so verify that we cannot create any more |
| 75 // inside the oncomplete event of an offline context to use for testing | 75 // nodes, nor connect any. |
| 76 // purposes. | 76 should(() => context.createAnalyser(), 'context.createAnalyser()') |
| 77 should(() => context.createBuffer(1, 1, 48000), | 77 .throw('InvalidStateError'); |
| 78 "context.createBuffer(1, 1, 48000)") | 78 should( |
| 79 .notThrow(); | 79 () => context.createBiquadFilter(), |
| 80 | 80 'context.createBiquadFilter()') |
| 81 should(() => context.createBufferSource(), | 81 .throw('InvalidStateError'); |
| 82 "context.createBufferSource()") | 82 |
| 83 .throw("InvalidStateError"); | 83 // createBuffer is an exception because it's not really tied in any |
| 84 should(() => context.createChannelMerger(), | 84 // way to an audio context. And it's useful to be able to create a |
| 85 "context.createChannelMerger()") | 85 // buffer inside the oncomplete event of an offline context to use |
| 86 .throw("InvalidStateError"); | 86 // for testing purposes. |
| 87 should(() => context.createChannelSplitter(), | 87 should( |
| 88 "context.createChannelSplitter()") | 88 () => context.createBuffer(1, 1, 48000), |
| 89 .throw("InvalidStateError"); | 89 'context.createBuffer(1, 1, 48000)') |
| 90 should(() => context.createConvolver(), "context.createConvolver()") | 90 .notThrow(); |
| 91 .throw("InvalidStateError"); | 91 |
| 92 should(() => context.createDelay(), "context.createDelay()") | 92 should( |
| 93 .throw("InvalidStateError"); | 93 () => context.createBufferSource(), |
| 94 should(() => | 94 'context.createBufferSource()') |
| 95 context.createDynamicsCompressor(), | 95 .throw('InvalidStateError'); |
| 96 "context.createDynamicsCompressor()").throw("InvalidStateError"); | 96 should( |
| 97 should(() => context.createGain(), "context.createGain()").throw( | 97 () => context.createChannelMerger(), |
| 98 "InvalidStateError"); | 98 'context.createChannelMerger()') |
| 99 should(() => context.createOscillator(), | 99 .throw('InvalidStateError'); |
| 100 "context.createOscillator()") | 100 should( |
| 101 .throw("InvalidStateError"); | 101 () => context.createChannelSplitter(), |
| 102 should(() => context.createPanner(), "context.createPanner()") | 102 'context.createChannelSplitter()') |
| 103 .throw("InvalidStateError"); | 103 .throw('InvalidStateError'); |
| 104 should(() => context.createPeriodicWave(wave, wave), | 104 should(() => context.createConvolver(), 'context.createConvolver()') |
| 105 "context.createPeriodicWave(wave, wave)") | 105 .throw('InvalidStateError'); |
| 106 .throw("InvalidStateError"); | 106 should(() => context.createDelay(), 'context.createDelay()') |
| 107 should(() => context.createScriptProcessor(), | 107 .throw('InvalidStateError'); |
| 108 "context.createScriptProcessor()") | 108 should( |
| 109 .throw("InvalidStateError"); | 109 () => context.createDynamicsCompressor(), |
| 110 should(() => | 110 'context.createDynamicsCompressor()') |
| 111 context.createStereoPanner(), "context.createStereoPanner()").throw( | 111 .throw('InvalidStateError'); |
| 112 "InvalidStateError"); | 112 should(() => context.createGain(), 'context.createGain()') |
| 113 should(() => context.createWaveShaper(), | 113 .throw('InvalidStateError'); |
| 114 "context.createWaveShaper()") | 114 should( |
| 115 .throw("InvalidStateError"); | 115 () => context.createOscillator(), 'context.createOscillator()') |
| 116 | 116 .throw('InvalidStateError'); |
| 117 should(() => osc.connect(gain), "osc.connect(gain)") | 117 should(() => context.createPanner(), 'context.createPanner()') |
| 118 .throw("InvalidStateError"); | 118 .throw('InvalidStateError'); |
| 119 should(() => gain.disconnect(), "gain.disconnect()").notThrow(); | 119 should( |
| 120 | 120 () => context.createPeriodicWave(wave, wave), |
| 121 // Can't resume a context that is closed (released). | 121 'context.createPeriodicWave(wave, wave)') |
| 122 should(context.resume(), "context.resume()") | 122 .throw('InvalidStateError'); |
| 123 .beRejected() | 123 should( |
| 124 .then(task.done.bind(task)); | 124 () => context.createScriptProcessor(), |
| 125 }); | 125 'context.createScriptProcessor()') |
| 126 | 126 .throw('InvalidStateError'); |
| 127 // Task: test online context (3). | 127 should( |
| 128 audit.define({ | 128 () => context.createStereoPanner(), |
| 129 label: 'test-online-context-3', | 129 'context.createStereoPanner()') |
| 130 description: "Close an online context again" | 130 .throw('InvalidStateError'); |
| 131 }, function (task, should) { | 131 should( |
| 132 // Try closing the context again. The promise should be rejected. | 132 () => context.createWaveShaper(), 'context.createWaveShaper()') |
| 133 should(context.close(), "context.close() again") | 133 .throw('InvalidStateError'); |
| 134 .beRejected() | 134 |
| 135 .then(() => { | 135 should(() => osc.connect(gain), 'osc.connect(gain)') |
| 136 // Finally, run GC. The context should be gone, but this seems | 136 .throw('InvalidStateError'); |
| 137 // difficult to verify. | 137 should(() => gain.disconnect(), 'gain.disconnect()').notThrow(); |
| 138 if (window.gc) | 138 |
| 139 gc(); | 139 // Can't resume a context that is closed (released). |
| 140 should(context.destination, "context.destination") | 140 should(context.resume(), 'context.resume()') |
| 141 .beEqualTo(null); | 141 .beRejected() |
| 142 }) | 142 .then(task.done.bind(task)); |
| 143 .then(task.done.bind(task)); | 143 }); |
| 144 }); | 144 |
| 145 | 145 // Task: test online context (3). |
| 146 // Task: test online context (4). | 146 audit.define( |
| 147 audit.define({ | 147 { |
| 148 label: 'test-online-context-4', | 148 label: 'test-online-context-3', |
| 149 description: "Test closed online context 4" | 149 description: 'Close an online context again' |
| 150 }, function (task, should) { | 150 }, |
| 151 // Create a context and verify that its sampleRate and baseLatency return | 151 function(task, should) { |
| 152 // valid values whether it's open or closed. | 152 // Try closing the context again. The promise should be rejected. |
| 153 should(() => context = new AudioContext(), | 153 should(context.close(), 'context.close() again') |
| 154 "context1 = new AudioContext()") | 154 .beRejected() |
| 155 .notThrow(); | 155 .then(() => { |
| 156 should(context.sampleRate, "context1.sampleRate") | 156 // Finally, run GC. The context should be gone, but this seems |
| 157 .beGreaterThan("0"); | 157 // difficult to verify. |
| 158 should(context.sampleRate, "context1.baseLatency") | 158 if (window.gc) |
| 159 .beGreaterThan("0"); | 159 gc(); |
| 160 | 160 should(context.destination, 'context.destination') |
| 161 should(context.close(), "context1.close()") | 161 .beEqualTo(null); |
| 162 .beResolved() | 162 }) |
| 163 .then(() => { | 163 .then(task.done.bind(task)); |
| 164 should(context.sampleRate, "After close, context1.sampleRate") | 164 }); |
| 165 .beGreaterThan("0"); | 165 |
| 166 should(context.sampleRate, "After close, context1.baseLatency") | 166 // Task: test online context (4). |
| 167 .beGreaterThan("0"); | 167 audit.define( |
| 168 }) | 168 { |
| 169 .then(task.done.bind(task)); | 169 label: 'test-online-context-4', |
| 170 }); | 170 description: 'Test closed online context 4' |
| 171 | 171 }, |
| 172 // Task: test offline context (1). | 172 function(task, should) { |
| 173 audit.define({ | 173 // Create a context and verify that its sampleRate and baseLatency |
| 174 label: 'test-offline-context-1', | 174 // return valid values whether it's open or closed. |
| 175 description: "Test offline context" | 175 should( |
| 176 }, function (task, should) { | 176 () => context = new AudioContext(), |
| 177 // For an offline context, verify that close is not defined. | 177 'context1 = new AudioContext()') |
| 178 should(() => offline = new OfflineAudioContext(1, 1000, 48000), | 178 .notThrow(); |
| 179 "offline = new OfflineAudioContext(1, 1000, 48000)") | 179 should(context.sampleRate, 'context1.sampleRate') |
| 180 .notThrow(); | 180 .beGreaterThan('0'); |
| 181 should(offline.state, "offline.state") | 181 should(context.sampleRate, 'context1.baseLatency') |
| 182 .beEqualTo("suspended"); | 182 .beGreaterThan('0'); |
| 183 should(offline.close, "offline.close") | 183 |
| 184 .beEqualTo(undefined); | 184 should(context.close(), 'context1.close()') |
| 185 task.done(); | 185 .beResolved() |
| 186 }); | 186 .then(() => { |
| 187 | 187 should(context.sampleRate, 'After close, context1.sampleRate') |
| 188 audit.run(); | 188 .beGreaterThan('0'); |
| 189 </script> | 189 should( |
| 190 </body> | 190 context.sampleRate, 'After close, context1.baseLatency') |
| 191 .beGreaterThan('0'); |
| 192 }) |
| 193 .then(task.done.bind(task)); |
| 194 }); |
| 195 |
| 196 // Task: test offline context (1). |
| 197 audit.define( |
| 198 { |
| 199 label: 'test-offline-context-1', |
| 200 description: 'Test offline context' |
| 201 }, |
| 202 function(task, should) { |
| 203 // For an offline context, verify that close is not defined. |
| 204 should( |
| 205 () => offline = new OfflineAudioContext(1, 1000, 48000), |
| 206 'offline = new OfflineAudioContext(1, 1000, 48000)') |
| 207 .notThrow(); |
| 208 should(offline.state, 'offline.state').beEqualTo('suspended'); |
| 209 should(offline.close, 'offline.close').beEqualTo(undefined); |
| 210 task.done(); |
| 211 }); |
| 212 |
| 213 audit.run(); |
| 214 </script> |
| 215 </body> |
| 191 </html> | 216 </html> |
| OLD | NEW |