| 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       // Resuming the context cannot be tested with the trybot or the Content | 
| 73     audit.defineTask('test-resume', function (done) { | 31       // Shell because it requires the physical audio device to run. | 
| 74 |  | 
| 75       // Multiple calls to resume should not be a problem. But we can't test |  | 
| 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     }); | 32     }); | 
| 96 | 33 | 
| 97     // Task: test the state after context closed. | 34     // Task: test corner cases. | 
| 98     audit.defineTask('test-after-close', function (done) { | 35     audit.defineTask('corner-cases', function (done) { | 
| 99 | 36 | 
| 100       // Render the offline context. | 37       Should('Calling multiple context.suspend()', function() { | 
| 101       osc.start(); | 38         context.suspend(); | 
|  | 39         context.suspend(); | 
|  | 40       }).notThrow(); | 
| 102 | 41 | 
| 103       // Test suspend/resume in tested promise pattern. We don't care about the | 42       context.close().then(function () { | 
| 104       // actual result of the offline rendering. | 43         Should('Calling context.suspend() after close()', context.suspend()) | 
| 105       shouldNotThrow("p3 = offlineContext.startRendering()"); | 44           .beRejected(); | 
| 106       p3.then(function () { |  | 
| 107         shouldBeEqualToString("offlineContext.state", "closed"); |  | 
| 108 | 45 | 
| 109         // suspend() should be rejected on a closed context. | 46         Should('Calling context.resume() after close()', context.resume()) | 
| 110         offlineContext.suspend().then( | 47           .beRejected().then(done); | 
| 111           handlePromise(testFailed, "offlineContext.suspend() on a closed contex
     t not rejected"), | 48       }); | 
| 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 | 49 | 
| 133       }); |  | 
| 134     }); | 50     }); | 
| 135 | 51 | 
| 136     audit.defineTask('finish-test', function (done) { | 52     audit.defineTask('finish-test', function (done) { | 
| 137       done(); | 53       done(); | 
| 138       finishJSTest(); | 54       finishJSTest(); | 
| 139     }); | 55     }); | 
| 140 | 56 | 
| 141     audit.runTasks( | 57     audit.runTasks( | 
| 142       'test-suspend', | 58       'interface', | 
| 143       'test-resume', | 59       'promise-resolution', | 
| 144       'test-after-close', | 60       'corner-cases', | 
| 145       'finish-test' | 61       'finish-test' | 
| 146     ); | 62     ); | 
| 147 | 63 | 
| 148     successfullyParsed = true; | 64     successfullyParsed = true; | 
| 149   </script> | 65   </script> | 
| 150 </body> | 66 </body> | 
| 151 </html> | 67 </html> | 
| OLD | NEW | 
|---|