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 |