Bug 1459265 [wpt PR 10852] - Move AudioContext tests to WPT, a=testonly
authorRaymond Toy <rtoy@chromium.org>
Tue, 15 May 2018 13:38:16 +0000
changeset 418587 ec6270ca64e1a8df3175a806ccb745900933e894
parent 418586 7eb1c0f8b5714878acb0dcb507f4ee3c1dc0514e
child 418588 f34462ac250eea30820e4c7def5becb9b2755c29
push id34007
push usercsabou@mozilla.com
push dateThu, 17 May 2018 09:47:02 +0000
treeherdermozilla-central@8fb36531f7d0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1459265, 10852, 745778, 1042858, 556962
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1459265 [wpt PR 10852] - Move AudioContext tests to WPT, a=testonly Automatic update from web-platform-testsMove AudioContext tests to WPT These tests pass on Firefox or fail due to bugs in Firefox. The remaining tests are somewhat Chrome-specific and aren't moved. Bug: 745778 Change-Id: Idb1e9ce94339032d7e2866232424c458635db646 Reviewed-on: https://chromium-review.googlesource.com/1042858 Commit-Queue: Raymond Toy <rtoy@chromium.org> Reviewed-by: Hongchan Choi <hongchan@chromium.org> Cr-Commit-Position: refs/heads/master@{#556962} -- wpt-commits: f9e2b07e0b6f90440d698c8961dff483e34b9ede wpt-pr: 10852
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html
testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html
testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -371061,16 +371061,34 @@
     ]
    ],
    "webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html": [
     [
      "/webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html": [
+    [
+     "/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html",
+     {}
+    ]
+   ],
+   "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html": [
+    [
+     "/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html",
+     {}
+    ]
+   ],
+   "webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html": [
+    [
+     "/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html": [
     [
      "/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html": [
     [
@@ -612056,16 +612074,28 @@
   "webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html": [
    "ce84d25460435564021a13dc9e26384bc30e9d96",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiocontext-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html": [
+   "03d32deacab7a98f3cce29562b84158e3f512668",
+   "testharness"
+  ],
+  "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html": [
+   "0ef6d19b75e1437ea71846d5a0d1af7dd426dc83",
+   "testharness"
+  ],
+  "webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html": [
+   "21ea30d8fa92e908da66e79fd127e8fa0203a4c5",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html": [
    "3e8b55e707434899be9af13334d935368579f1dc",
    "testharness"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Testing AudioContext.getOutputTimestamp() method
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let audit = Audit.createTaskRunner();
+
+      audit.define('getoutputtimestamp-initial-values', function(task, should) {
+        let context = new AudioContext;
+        let timestamp = context.getOutputTimestamp();
+
+        should(timestamp.contextTime, 'timestamp.contextTime').exist();
+        should(timestamp.performanceTime, 'timestamp.performanceTime').exist();
+
+        should(timestamp.contextTime, 'timestamp.contextTime').beEqualTo(0);
+        should(timestamp.performanceTime, 'timestamp.performanceTime')
+            .beEqualTo(0);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test AudioContext.suspend() and AudioContext.resume()
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let offlineContext;
+      let osc;
+      let p1;
+      let p2;
+      let p3;
+
+      let sampleRate = 44100;
+      let durationInSeconds = 1;
+
+      let audit = Audit.createTaskRunner();
+
+      // Task: test suspend().
+      audit.define(
+          {
+            label: 'test-suspend',
+            description: 'Test suspend() for offline context'
+          },
+          function(task, should) {
+            // Test suspend/resume.  Ideally this test is best with a online
+            // AudioContext, but content shell doesn't really have a working
+            // online AudioContext. Hence, use an OfflineAudioContext. Not all
+            // possible scenarios can be easily checked with an offline context
+            // instead of an online context.
+
+            // Create an audio context with an oscillator.
+            should(
+                () => {
+                  offlineContext = new OfflineAudioContext(
+                      1, durationInSeconds * sampleRate, sampleRate);
+                },
+                'offlineContext = new OfflineAudioContext(1, ' +
+                    (durationInSeconds * sampleRate) + ', ' + sampleRate + ')')
+                .notThrow();
+            osc = offlineContext.createOscillator();
+            osc.connect(offlineContext.destination);
+
+            // Verify the state.
+            should(offlineContext.state, 'offlineContext.state')
+                .beEqualTo('suspended');
+
+            // Multiple calls to suspend() should not be a problem. But we can't
+            // test that on an offline context.  Thus, check that suspend() on
+            // an OfflineAudioContext rejects the promise.
+            should(
+                () => p1 = offlineContext.suspend(),
+                'p1 = offlineContext.suspend()')
+                .notThrow();
+            should(p1 instanceof Promise, 'p1 instanceof Promise').beTrue();
+
+            should(p1, 'p1').beRejected().then(task.done.bind(task));
+          });
+
+
+      // Task: test resume().
+      audit.define(
+          {
+            label: 'test-resume',
+            description: 'Test resume() for offline context'
+          },
+          function(task, should) {
+            // Multiple calls to resume should not be a problem. But we can't
+            // test that on an offline context. Thus, check that resume() on an
+            // OfflineAudioContext rejects the promise.
+            should(
+                () => p2 = offlineContext.resume(),
+                'p2 = offlineContext.resume()')
+                .notThrow();
+            should(p2 instanceof Promise, 'p2 instanceof Promise').beTrue();
+
+            // Resume doesn't actually resume an offline context
+            should(offlineContext.state, 'After resume, offlineContext.state')
+                .beEqualTo('suspended');
+            should(p2, 'p2').beRejected().then(task.done.bind(task));
+          });
+
+      // Task: test the state after context closed.
+      audit.define(
+          {
+            label: 'test-after-close',
+            description: 'Test state after context closed'
+          },
+          function(task, should) {
+            // Render the offline context.
+            osc.start();
+
+            // Test suspend/resume in tested promise pattern. We don't care
+            // about the actual result of the offline rendering.
+            should(
+                () => p3 = offlineContext.startRendering(),
+                'p3 = offlineContext.startRendering()')
+                .notThrow();
+
+            p3.then(() => {
+              should(offlineContext.state, 'After close, offlineContext.state')
+                  .beEqualTo('closed');
+
+              // suspend() should be rejected on a closed context.
+              should(offlineContext.suspend(), 'offlineContext.suspend()')
+                  .beRejected()
+                  .then(() => {
+                    // resume() should be rejected on closed context.
+                    should(offlineContext.resume(), 'offlineContext.resume()')
+                        .beRejected()
+                        .then(task.done.bind(task));
+                  })
+            });
+          });
+
+      audit.define(
+          {
+            label: 'resume-running-context',
+            description: 'Test resuming a running context'
+          },
+          (task, should) => {
+            let context;
+            should(() => context = new AudioContext(), 'Create online context')
+                .notThrow();
+
+            should(context.state, 'context.state').beEqualTo('running');
+            should(context.resume(), 'context.resume')
+                .beResolved()
+                .then(() => {
+                  should(context.state, 'context.state after resume')
+                      .beEqualTo('running');
+                })
+                .then(() => task.done());
+          });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test AudioContextOptions
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+      let defaultLatency;
+      let interactiveLatency;
+      let balancedLatency;
+      let playbackLatency;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define(
+          {
+            label: 'test-audiocontextoptions-latencyHint-basic',
+            description: 'Test creating contexts with basic latencyHint types.'
+          },
+          function(task, should) {
+            let closingPromises = [];
+
+            // Verify that an AudioContext can be created with default options.
+            should(function() {
+              context = new AudioContext()
+            }, 'context = new AudioContext()').notThrow();
+
+            should(context.sampleRate,
+              `context.sampleRate (${context.sampleRate} Hz)`).beGreaterThan(0);
+
+            defaultLatency = context.baseLatency;
+            should(defaultLatency, 'default baseLatency').beGreaterThan(0);
+
+            // Verify that an AudioContext can be created with the expected
+            // latency types.
+            should(
+                function() {
+                  context = new AudioContext({'latencyHint': 'interactive'})
+                },
+                'context = new AudioContext({\'latencyHint\': \'interactive\'})')
+                .notThrow();
+
+            interactiveLatency = context.baseLatency;
+            should(interactiveLatency, 'interactive baseLatency')
+                .beEqualTo(defaultLatency);
+            closingPromises.push(context.close());
+
+            should(
+                function() {
+                  context = new AudioContext({'latencyHint': 'balanced'})
+                },
+                'context = new AudioContext({\'latencyHint\': \'balanced\'})')
+                .notThrow();
+
+            balancedLatency = context.baseLatency;
+            should(balancedLatency, 'balanced baseLatency')
+                .beGreaterThanOrEqualTo(interactiveLatency);
+            closingPromises.push(context.close());
+
+            should(
+                function() {
+                  context = new AudioContext({'latencyHint': 'playback'})
+                },
+                'context = new AudioContext({\'latencyHint\': \'playback\'})')
+                .notThrow();
+
+            playbackLatency = context.baseLatency;
+            should(playbackLatency, 'playback baseLatency')
+                .beGreaterThanOrEqualTo(balancedLatency);
+            closingPromises.push(context.close());
+
+            Promise.all(closingPromises).then(function() {
+              task.done();
+            });
+          });
+
+      audit.define(
+          {
+            label: 'test-audiocontextoptions-latencyHint-double',
+            description:
+                'Test creating contexts with explicit latencyHint values.'
+          },
+          function(task, should) {
+            let closingPromises = [];
+
+            // Verify too small exact latency clamped to 'interactive'
+            should(
+                function() {
+                  context =
+                      new AudioContext({'latencyHint': interactiveLatency / 2})
+                },
+                'context = new AudioContext({\'latencyHint\': ' +
+                    'interactiveLatency/2})')
+                .notThrow();
+            should(context.baseLatency, 'double-constructor baseLatency small')
+                .beLessThanOrEqualTo(interactiveLatency);
+            closingPromises.push(context.close());
+
+            // Verify that exact latency in range works as expected
+            let validLatency = (interactiveLatency + playbackLatency) / 2;
+            should(
+                function() {
+                  context = new AudioContext({'latencyHint': validLatency})
+                },
+                'context = new AudioContext({\'latencyHint\': validLatency})')
+                .notThrow();
+            should(
+                context.baseLatency, 'double-constructor baseLatency inrange 1')
+                .beGreaterThanOrEqualTo(interactiveLatency);
+            should(
+                context.baseLatency, 'double-constructor baseLatency inrange 2')
+                .beLessThanOrEqualTo(playbackLatency);
+            closingPromises.push(context.close());
+
+            // Verify too big exact latency clamped to some value
+            let context1;
+            let context2;
+            should(function() {
+              context1 =
+                  new AudioContext({'latencyHint': playbackLatency * 10});
+              context2 =
+                  new AudioContext({'latencyHint': playbackLatency * 20});
+            }, 'creating two high latency contexts').notThrow();
+            should(context1.baseLatency, 'high latency context baseLatency')
+                .beEqualTo(context2.baseLatency);
+            should(context1.baseLatency, 'high latency context baseLatency')
+                .beGreaterThan(interactiveLatency);
+            closingPromises.push(context1.close());
+            closingPromises.push(context2.close());
+
+            // Verify that invalid latencyHint values are rejected.
+            should(
+                function() {
+                  context = new AudioContext({'latencyHint': 'foo'})
+                },
+                'context = new AudioContext({\'latencyHint\': \'foo\'})')
+                .throw('TypeError');
+
+            // Verify that no extra options can be passed into the
+            // AudioContextOptions.
+            should(
+                function() {
+                  context = new AudioContext('latencyHint')
+                },
+                'context = new AudioContext(\'latencyHint\')')
+                .throw('TypeError');
+
+            Promise.all(closingPromises).then(function() {
+              task.done();
+            });
+          });
+
+      audit.run();
+    </script>
+  </body>
+</html>