OLD | NEW |
---|---|
1 <!doctype html> | 1 <!doctype html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
4 <title>Test AudioContext.suspend() and AudioContext.resume()</title> | 4 <title>Test AudioContext.suspend() and AudioContext.resume()</title> |
5 <script src="../resources/js-test.js"></script> | 5 <script src="../resources/js-test.js"></script> |
6 <script src="resources/compatibility.js"></script> | 6 <script src="resources/compatibility.js"></script> |
7 <script src="resources/audio-testing.js"></script> | 7 <script src="resources/audio-testing.js"></script> |
8 </head> | 8 </head> |
9 | 9 |
10 <body> | 10 <body> |
11 <script> | 11 <script> |
12 description("Test suspend/resume for an (offline) AudioContext"); | 12 description("Test suspend/resume for an AudioContext"); |
13 window.jsTestIsAsync = true; | 13 window.jsTestIsAsync = true; |
14 | 14 |
15 var offlineContext; | 15 var context = new AudioContext(); |
16 var osc; | |
17 var p1; | |
18 var p2; | |
19 var p3; | |
20 | |
21 var sampleRate = 44100; | |
22 var durationInSeconds = 1; | |
23 | 16 |
24 var audit = Audit.createTaskRunner(); | 17 var audit = Audit.createTaskRunner(); |
25 | 18 |
26 // Convenience function that returns a function that calls the |passFailFunc | | 19 // Task: check the method interface. |
27 // with the given |message|. The |passFailFunc| should be either |testPasse d| | 20 audit.defineTask('interface', function (done) { |
28 // or |testFailed|. | 21 Should('typeof context.suspend()', typeof context.suspend).beEqualTo('func tion'); |
29 function handlePromise(passFailFunc, message) { | 22 Should('typeof context.resume()', typeof context.resume).beEqualTo('functi on'); |
30 return function () { | 23 done(); |
31 passFailFunc(message); | |
32 }; | |
33 } | |
34 | |
35 // Task: test suspend(). | |
36 audit.defineTask('test-suspend', function (done) { | |
37 | |
38 // Test suspend/resume. Ideally this test is best with a online | |
39 // AudioContext, but content shell doesn't really have a working online | |
40 // AudioContext. Hence, use an OfflineAudioContext. Not all possible | |
41 // scenarios can be easily checked with an offline context instead of an | |
42 // online context. | |
43 | |
44 // Create an audio context with an oscillator. | |
45 shouldNotThrow("offlineContext = new OfflineAudioContext(1, durationInSeco nds * sampleRate, sampleRate)"); | |
46 osc = offlineContext.createOscillator(); | |
47 osc.connect(offlineContext.destination); | |
48 | |
49 // Verify the state. | |
50 shouldBeEqualToString("offlineContext.state", "suspended"); | |
51 | |
52 // Multiple calls to suspend() should not be a problem. But we can't test | |
53 // that on an offline context. Thus, check that suspend() on an | |
54 // OfflineAudioContext rejects the promise. | |
55 shouldNotThrow("p1 = offlineContext.suspend()"); | |
56 shouldBeType("p1", "Promise"); | |
57 p1.then( | |
58 handlePromise(testFailed, "offlineContext.suspend() should have been rej ected for an offline context"), | |
59 function (e) { | |
60 if (e.name === "InvalidAccessError") { | |
61 testPassed( | |
62 "offlineContext.suspend() was correctly rejected: " + e); | |
63 } else { | |
64 testFailed( | |
65 "offlineContext.suspend() was correctly rejected but expected Inva lidAccessError, not: " + e); | |
66 } | |
67 } | |
68 ).then(done); | |
69 }); | 24 }); |
70 | 25 |
26 // Task: check the promise resolution. | |
27 audit.defineTask('promise-resolution', function (done) { | |
28 Should('context.suspend()', context.suspend()).beResolved().then(done); | |
71 | 29 |
72 // Task: test resume(). | 30 // Note that the following does not work in the ContentShell or a trybot |
73 audit.defineTask('test-resume', function (done) { | 31 // which has no physical audio device for real-time rendering. |
74 | 32 // |
75 // Multiple calls to resume should not be a problem. But we can't test | 33 // Should('context.resume()', context.resume()).beResolved(); |
76 // that on an offline context. Thus, check that resume() on an | |
77 // OfflineAudioContext rejects the promise. | |
78 shouldNotThrow("p2 = offlineContext.resume()"); | |
79 shouldBeType("p2", "Promise"); | |
80 | |
81 // Resume doesn't actually resume an offline context | |
82 shouldBeEqualToString("offlineContext.state", "suspended"); | |
83 p2.then( | |
84 handlePromise(testFailed, "offlineContext.resume() should have been reje cted for an offline context"), | |
85 function (e) { | |
86 if (e.name === "InvalidAccessError") { | |
87 testPassed( | |
88 "offlineContext.resume() was correctly rejected: " + e); | |
89 } else { | |
90 testFailed( | |
91 "offlineContext.resume() was correctly rejected but expected Inval idAccessError, not: " + e); | |
92 } | |
93 } | |
94 ).then(done); | |
95 }); | 34 }); |
96 | 35 |
97 // Task: test the state after context closed. | 36 // Task: test corner cases. |
98 audit.defineTask('test-after-close', function (done) { | 37 audit.defineTask('corner-cases', function (done) { |
99 | 38 |
100 // Render the offline context. | 39 // With the same reason above, this test is only valid for the complete |
101 osc.start(); | 40 // browser, not for the ContentShell or a trybot. |
41 // | |
42 // Should('Calling multiple context.resume()', function() { | |
43 // context.resume(); | |
44 // context.resume(); | |
45 // }).notThrow(); | |
Raymond Toy
2015/06/12 21:11:36
Remove the commented-out code. And update comment
hongchan
2015/06/15 18:40:45
Done.
| |
102 | 46 |
103 // Test suspend/resume in tested promise pattern. We don't care about the | 47 Should('Calling multiple context.suspend()', function() { |
104 // actual result of the offline rendering. | 48 context.suspend(); |
105 shouldNotThrow("p3 = offlineContext.startRendering()"); | 49 context.suspend(); |
106 p3.then(function () { | 50 }).notThrow(); |
107 shouldBeEqualToString("offlineContext.state", "closed"); | |
108 | 51 |
109 // suspend() should be rejected on a closed context. | 52 context.close().then(function () { |
110 offlineContext.suspend().then( | 53 Should('Calling context.suspend() after close()', context.suspend()) |
111 handlePromise(testFailed, "offlineContext.suspend() on a closed contex t not rejected"), | 54 .beRejected(); |
112 function (e) { | |
113 if (e.name === "InvalidAccessError") { | |
114 testPassed("offlineContext.suspend() on a closed context rejected: " + e); | |
115 } else { | |
116 testFailed("offlineContext.suspend() on a closed context rejected but expected InvalidAccessError, not: " + e); | |
117 } | |
118 } | |
119 ).then(function () { | |
120 // resume() should be rejected on closed context. | |
121 offlineContext.resume().then( | |
122 handlePromise(testFailed, "offlineContext.resume() on a closed conte xt not rejected"), | |
123 function (e) { | |
124 if (e.name === "InvalidAccessError") { | |
125 testPassed("offlineContext.resume() on a closed context rejected : " + e); | |
126 } else { | |
127 testFailed("offlineContext.resume() on a closed context rejected but expected InvalidAccessError, not: " + e); | |
128 } | |
129 } | |
130 ).then(done); | |
131 }); | |
132 | 55 |
56 Should('Calling context.resume() after close()', context.resume()) | |
57 .beRejected().then(done); | |
133 }); | 58 }); |
59 | |
134 }); | 60 }); |
135 | 61 |
136 audit.defineTask('finish-test', function (done) { | 62 audit.defineTask('finish-test', function (done) { |
137 done(); | 63 done(); |
138 finishJSTest(); | 64 finishJSTest(); |
139 }); | 65 }); |
140 | 66 |
141 audit.runTasks( | 67 audit.runTasks( |
142 'test-suspend', | 68 'interface', |
143 'test-resume', | 69 'promise-resolution', |
144 'test-after-close', | 70 'corner-cases', |
145 'finish-test' | 71 'finish-test' |
146 ); | 72 ); |
147 | 73 |
148 successfullyParsed = true; | 74 successfullyParsed = true; |
149 </script> | 75 </script> |
150 </body> | 76 </body> |
151 </html> | 77 </html> |
OLD | NEW |