From 6b9d7dc858f817332425c5d7c64bb3aece1b5de3 Mon Sep 17 00:00:00 2001
From: Koushik <koushikbug123@gmail.com>
Date: Wed, 26 Mar 2025 13:35:04 -0700
Subject: [PATCH] Migrate webaudio/MediaStreamAudioSource to testharness.js

The following test files have been deprecated from audit.js to
testharness.js:
- added testInvalidConstructor_TH() in audionodeoptions.js
- renamed ctor-mediastreamaudiosourcenode.html to constructor.html
- mediastreamaudiosourcenode.html

Bug: 396477778

Change-Id: I03eb960cadd0aa03ea4b1bacdaeb4c0243779de7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6345010
Reviewed-by: Michael Wilson <mjwilson@chromium.org>
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1438366}
---
 AUTHORS                                       |   1 +
 .../MediaStreamAudioSource/constructor.html   |  41 ++++++
 .../ctor-mediastreamaudiosource.html          |  53 --------
 .../mediastreamaudiosourcenode.html           | 121 ++++++++----------
 .../webaudio/resources/audionodeoptions.js    |  33 +++++
 5 files changed, 125 insertions(+), 124 deletions(-)
 create mode 100644 third_party/blink/web_tests/webaudio/MediaStreamAudioSource/constructor.html
 delete mode 100644 third_party/blink/web_tests/webaudio/MediaStreamAudioSource/ctor-mediastreamaudiosource.html

diff --git a/AUTHORS b/AUTHORS
index e07c174ae0373..3ba54493b1619 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -828,6 +828,7 @@ Kirill Ovchinnikov <kirill.ovchinn@gmail.com>
 Klemen Forstnerič <klemen.forstneric@gmail.com>
 Kodam Nagaraju <k2.nagaraju@samsung.com>
 Konrad Dzwinel <kdzwinel@gmail.com>
+Koushik Kumar Bug <koushikbug123@gmail.com>
 Kousuke Takaki <yoseio@brainoid.dev>
 Kovacs Zeteny <brightbulbapp@gmail.com>
 Krishna Chaitanya <krish.botta@samsung.com>
diff --git a/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/constructor.html b/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/constructor.html
new file mode 100644
index 0000000000000..806ebba8fbe85
--- /dev/null
+++ b/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/constructor.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Test MediaStreamAudioSourceNode constructor</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script>
+      'use strict';
+
+      let context;
+
+      test(() => {
+        context = new AudioContext();
+        assert_true(
+            context instanceof AudioContext,
+            'The context is an instance of AudioContext'
+        );
+      }, 'The AudioContext constructor should NOT throw');
+
+      testInvalidConstructor_TH('MediaStreamAudioSourceNode', context);
+
+      test(() => {
+        assert_throws_js(
+            TypeError,
+            () => new MediaStreamAudioSourceNode(context),
+            'The constructor with insufficient arguments should fail'
+        );
+
+        const options = { mediaStream: new MediaStream() };
+        assert_throws_dom(
+            'InvalidStateError',
+            () => new MediaStreamAudioSourceNode(context,options),
+            'The constructor with an empty MediaStream instance'
+        );
+      },  'Exceptions from invalid constructor usage');
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/ctor-mediastreamaudiosource.html b/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/ctor-mediastreamaudiosource.html
deleted file mode 100644
index 0edf31bf747f3..0000000000000
--- a/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/ctor-mediastreamaudiosource.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>
-      Test Constructor: MediaStreamAudioSource
-    </title>
-    <script src="../../resources/testharness.js"></script>
-    <script src="../../resources/testharnessreport.js"></script>
-    <script src="../resources/audit-util.js"></script>
-    <script src="../resources/audit.js"></script>
-    <script src="../resources/audionodeoptions.js"></script>
-  </head>
-  <body>
-    <script id="layout-test-code">
-      let context;
-
-      let audit = Audit.createTaskRunner();
-
-      audit.define('initialize', (task, should) => {
-        // Need AudioContext, not OfflineAudioContext, for these tests.
-        should(() => {
-          context = new AudioContext();
-        }, 'context = new AudioContext()').notThrow();
-        task.done();
-      });
-
-      audit.define('invalid constructor', (task, should) => {
-        testInvalidConstructor(should, 'MediaStreamAudioSourceNode', context);
-        task.done();
-      });
-
-      audit.define('constructor options', (task, should) => {
-        let node;
-
-        let options = {mediaStream: new MediaStream()};
-
-        // We throw because the mediaStream has no tracks. But otherwise the
-        // constructor worked.
-        should(
-            () => {
-              node = new MediaStreamAudioSourceNode(context, options);
-            },
-            'node = new MediaStreamAudioSourceNode(context, ' +
-                JSON.stringify(options) + ')')
-            .throw(DOMException, 'InvalidStateError');
-
-        task.done();
-      });
-
-      audit.run();
-    </script>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/mediastreamaudiosourcenode.html b/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/mediastreamaudiosourcenode.html
index 177d21ae47402..e2affc754e99a 100644
--- a/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/mediastreamaudiosourcenode.html
+++ b/third_party/blink/web_tests/webaudio/MediaStreamAudioSource/mediastreamaudiosourcenode.html
@@ -1,91 +1,70 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <title>
-      mediastreamaudiosourcenode.html
-    </title>
+    <title>MediaStreamAudioSourceNode: Test For API Functionality</title>
     <script src="../../resources/testharness.js"></script>
     <script src="../../resources/testharnessreport.js"></script>
-    <script src="../resources/audit-util.js"></script>
-    <script src="../resources/audit.js"></script>
   </head>
   <body>
-    <script id="layout-test-code">
-      let audit = Audit.createTaskRunner();
+    <script>
+      'use strict';
 
-      audit.define(
-          {
-            label: 'test',
-            description: 'Basic tests for MediaStreamAudioSourceNode API'
-          },
-          (task, should) => {
-            should(
-                () => {navigator.webkitGetUserMedia(
-                    {audio: true},
-                    (stream) => {
-                      gotStream(stream, should);
-                      task.done();
-                    },
-                    () => {
-                      should(false, 'Stream generation')
-                          .message('succeeded', 'failed');
-                      task.done();
-                    })},
-                'getUserMedia()')
-                .notThrow();
-          });
+      async function testMediaStreamAudioSourceNode() {
+        let stream;
+        try {
+          stream =
+              await navigator.mediaDevices.getUserMedia({ audio: true });
+        } catch (error) {
+          throw new TestAbortedError(
+              `getUserMedia failed: ${error.name} - ${error.message}. ` +
+              'Test did not run as expected'
+          );
+        }
 
-      audit.run();
+        const context = new AudioContext();
+        const mediaStreamSource =
+            new MediaStreamAudioSourceNode(context, { mediaStream: stream });
 
-      function gotStream(stream, should) {
-        should(true, '{audio:true} generated stream').message('correctly', '');
-
-        let context = new AudioContext();
-
-        // Create an AudioNode from the stream.
-        let mediaStreamSource = context.createMediaStreamSource(stream);
-
-        // Check number of inputs and outputs.
-        should(
+        assert_equals(
             mediaStreamSource.numberOfInputs,
-            'mediaStreamSource.numberOfInputs')
-            .beEqualTo(0);
-        should(
+            0,
+            'mediaStreamSource.numberOfInputs should be 0');
+
+        assert_equals(
             mediaStreamSource.numberOfOutputs,
-            'mediaStreamSource.numberOfOutputs')
-            .beEqualTo(1);
+            1,
+            'mediaStreamSource.numberOfOutputs should be 1');
 
-        // Verify the same object is returned
-        let element = mediaStreamSource.mediaStream;
-        should(
-            element instanceof MediaStream,
-            'mediaStreamSource.mediaStream instanceof MediaStream')
-            .beTrue();
-        should(
-            mediaStreamSource.mediaStream === element,
-            'mediaStreamSource.mediaStream is same object')
-            .beTrue();
+        const mediaStream = mediaStreamSource.mediaStream;
+        assert_true(
+            mediaStream instanceof MediaStream,
+            'mediaStreamSource.mediaStream should be a MediaStream');
 
-        // Try calling connect() method with illegal values.
-        should(
+        assert_true(
+            mediaStreamSource.mediaStream === mediaStream,
+            'mediaStreamSource.mediaStream should be the same object');
+
+        assert_throws_js(
+            TypeError,
             () => mediaStreamSource.connect(0, 0, 0),
-            'mediaStreamSource.connect(0, 0, 0)')
-            .throw();
-        should(
-            () => mediaStreamSource.connect(context.destination, 5, 0),
-            'mediaStreamSource.connect(context.destination, 5, 0)')
-            .throw();
-        should(
-            () => mediaStreamSource.connect(context.destination, 0, 5),
-            'mediaStreamSource.connect(context.destination, 0, 5)')
-            .throw();
+            'connect with non-AudioNode throws TypeError');
 
-        // Try calling connect() with proper values.
-        should(
-            () => mediaStreamSource.connect(context.destination, 0, 0),
-            'mediaStreamSource.connect(context.destination, 0, 0)')
-            .notThrow();
+        assert_throws_dom(
+            'IndexSizeError',
+            () => mediaStreamSource.connect(context.destination, 5, 0),
+            'connect with invalid output index throws IndexSizeError');
+
+        assert_throws_dom(
+            'IndexSizeError',
+            () => mediaStreamSource.connect(context.destination, 0, 5),
+            'connect with invalid input index throws IndexSizeError');
+
+        mediaStreamSource.connect(context.destination, 0, 0);
       }
+
+      promise_test(
+        () => testMediaStreamAudioSourceNode(),
+        'Basic API tests for MediaStreamAudioSourceNode');
     </script>
   </body>
 </html>
diff --git a/third_party/blink/web_tests/webaudio/resources/audionodeoptions.js b/third_party/blink/web_tests/webaudio/resources/audionodeoptions.js
index 03abde2fe5f93..941492a247221 100644
--- a/third_party/blink/web_tests/webaudio/resources/audionodeoptions.js
+++ b/third_party/blink/web_tests/webaudio/resources/audionodeoptions.js
@@ -209,6 +209,39 @@ function testInvalidConstructor(should, name, context) {
   }, 'new ' + name + '(context, 42)').throw(TypeError);
 }
 
+// TODO(crbug.com/406463484): Remove _TH suffix when audit.js is deprecated.
+/**
+ * Tests invalid constructor scenarios for a given Web Audio node constructor
+ * using testharness.js.
+ * Verifies that the constructor throws TypeError for common misuse cases:
+ * - No arguments provided.
+ * - Invalid context (e.g., a number instead of an AudioContext).
+ * - Valid context with invalid options (e.g., a number instead of an object).
+ *
+ * @param {string} constructorName - The name of the Web Audio node constructor
+ * to test (e.g., 'MediaStreamAudioSourceNode').
+ * @param {AudioContext} context - A valid AudioContext instance to use in the
+ * constructor tests.
+ */
+function testInvalidConstructor_TH(constructorName, context) {
+  test(function () {
+    assert_throws_js(
+        TypeError, () => {
+          new window[constructorName]();
+    }, `new ${constructorName}() should throw TypeError`);
+
+    assert_throws_js(
+        TypeError, () => {
+          new window[constructorName](1);
+    }, `new ${constructorName}(1) should throw TypeError`);
+
+    assert_throws_js(
+        TypeError, () => {
+          new window[constructorName](context, 42);
+    }, `new ${name}(context, 42) should throw TypeError`);
+  }, `Invalid constructor tests for ${constructorName}`);
+}
+
 function testDefaultConstructor(should, name, context, options) {
   let node;