From 79c43ae47794e7d09253f26e4a5f6a0666f28719 Mon Sep 17 00:00:00 2001
From: Antoine du Hamel <duhamelantoine1995@gmail.com>
Date: Mon, 25 Jul 2022 00:00:03 +0200
Subject: [PATCH 1/3] test_runner: validate `concurrency` option

---
 lib/internal/test_runner/test.js              | 28 +++++++++++++------
 .../parallel/test-runner-option-validation.js | 11 ++++++++
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js
index 1663958f9b7c94..ff4840f0690910 100644
--- a/lib/internal/test_runner/test.js
+++ b/lib/internal/test_runner/test.js
@@ -33,9 +33,10 @@ const {
 } = require('internal/util');
 const { isPromise } = require('internal/util/types');
 const {
-  isUint32,
   validateAbortSignal,
   validateNumber,
+  validateUint32,
+  validateOneOf,
 } = require('internal/validators');
 const { setTimeout } = require('timers/promises');
 const { TIMEOUT_MAX } = require('internal/timers');
@@ -149,14 +150,23 @@ class Test extends AsyncResource {
       this.timeout = parent.timeout;
     }
 
-    if (isUint32(concurrency) && concurrency !== 0) {
-      this.concurrency = concurrency;
-    } else if (typeof concurrency === 'boolean') {
-      if (concurrency) {
-        this.concurrency = isTestRunner ? MathMax(cpus().length - 1, 1) : Infinity;
-      } else {
-        this.concurrency = 1;
-      }
+    switch (typeof concurrency) {
+      case 'number':
+        validateUint32(concurrency, 'concurrency', 1);
+        this.concurrency = concurrency;
+        break;
+
+      case 'boolean':
+        if (concurrency) {
+          this.concurrency = isTestRunner ? MathMax(cpus().length - 1, 1) : Infinity;
+        } else {
+          this.concurrency = 1;
+        }
+        break;
+
+      default:
+        if (concurrency != null)
+          validateOneOf(concurrency, 'concurrency', ['boolean', 'number']);
     }
 
     if (timeout != null && timeout !== Infinity) {
diff --git a/test/parallel/test-runner-option-validation.js b/test/parallel/test-runner-option-validation.js
index a6b7cb1826b166..5de98b867bba21 100644
--- a/test/parallel/test-runner-option-validation.js
+++ b/test/parallel/test-runner-option-validation.js
@@ -13,3 +13,14 @@ const test = require('node:test');
   // Valid values should not throw.
   test({ timeout });
 });
+
+[Symbol(), {}, [], () => {}, 1n, '1'].forEach((concurrency) => {
+  assert.throws(() => test({ concurrency }), { code: 'ERR_INVALID_ARG_TYPE' });
+});
+[-1, 0, 1.1, -Infinity, NaN, 2 ** 33, Number.MAX_SAFE_INTEGER].forEach((concurrency) => {
+  assert.throws(() => test({ concurrency }), { code: 'ERR_OUT_OF_RANGE' });
+});
+[null, undefined, 1, 2 ** 31].forEach((concurrency) => {
+  // Valid values should not throw.
+  test({ concurrency });
+});

From 944b575738b297876ba29a0dff385f45ae36727c Mon Sep 17 00:00:00 2001
From: Antoine du Hamel <duhamelantoine1995@gmail.com>
Date: Mon, 25 Jul 2022 00:42:09 +0200
Subject: [PATCH 2/3] fixup! test_runner: validate `concurrency` option

---
 lib/internal/test_runner/test.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js
index ff4840f0690910..89b8c196038549 100644
--- a/lib/internal/test_runner/test.js
+++ b/lib/internal/test_runner/test.js
@@ -19,6 +19,7 @@ const { once } = require('events');
 const { AbortController } = require('internal/abort_controller');
 const {
   codes: {
+    ERR_INVALID_ARG_TYPE,
     ERR_TEST_FAILURE,
   },
   kIsNodeError,
@@ -36,7 +37,6 @@ const {
   validateAbortSignal,
   validateNumber,
   validateUint32,
-  validateOneOf,
 } = require('internal/validators');
 const { setTimeout } = require('timers/promises');
 const { TIMEOUT_MAX } = require('internal/timers');
@@ -152,7 +152,7 @@ class Test extends AsyncResource {
 
     switch (typeof concurrency) {
       case 'number':
-        validateUint32(concurrency, 'concurrency', 1);
+        validateUint32(concurrency, 'options.concurrency', 1);
         this.concurrency = concurrency;
         break;
 
@@ -166,7 +166,7 @@ class Test extends AsyncResource {
 
       default:
         if (concurrency != null)
-          validateOneOf(concurrency, 'concurrency', ['boolean', 'number']);
+          throw new ERR_INVALID_ARG_TYPE('options.concurrency', ['boolean', 'number'], concurrency);
     }
 
     if (timeout != null && timeout !== Infinity) {

From 6ff9dd62da33390e033eee1353b8cf68b839481b Mon Sep 17 00:00:00 2001
From: Antoine du Hamel <duhamelantoine1995@gmail.com>
Date: Mon, 25 Jul 2022 00:43:37 +0200
Subject: [PATCH 3/3] fixup! test_runner: validate `concurrency` option

---
 test/parallel/test-runner-option-validation.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/parallel/test-runner-option-validation.js b/test/parallel/test-runner-option-validation.js
index 5de98b867bba21..9d0129253613f2 100644
--- a/test/parallel/test-runner-option-validation.js
+++ b/test/parallel/test-runner-option-validation.js
@@ -20,7 +20,7 @@ const test = require('node:test');
 [-1, 0, 1.1, -Infinity, NaN, 2 ** 33, Number.MAX_SAFE_INTEGER].forEach((concurrency) => {
   assert.throws(() => test({ concurrency }), { code: 'ERR_OUT_OF_RANGE' });
 });
-[null, undefined, 1, 2 ** 31].forEach((concurrency) => {
+[null, undefined, 1, 2 ** 31, true, false].forEach((concurrency) => {
   // Valid values should not throw.
   test({ concurrency });
 });