Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull latest commits from node core #32

Merged
merged 5 commits into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ internally.
- `only` {boolean} If truthy, and the test context is configured to run
`only` tests, then this test will be run. Otherwise, the test is skipped.
**Default:** `false`.
* `signal` {AbortSignal} Allows aborting an in-progress test
* `signal` {AbortSignal} Allows aborting an in-progress test.
- `skip` {boolean|string} If truthy, the test is skipped. If a string is
provided, that string is displayed in the test results as the reason for
skipping the test. **Default:** `false`.
Expand Down Expand Up @@ -506,6 +506,7 @@ execution of the test function. This function does not return a value.
- `skip` {boolean|string} If truthy, the test is skipped. If a string is
provided, that string is displayed in the test results as the reason for
skipping the test. **Default:** `false`.
- `signal` {AbortSignal} Allows aborting an in-progress test.
- `todo` {boolean|string} If truthy, the test marked as `TODO`. If a string
is provided, that string is displayed in the test results as the reason why
the test is `TODO`. **Default:** `false`.
Expand Down
11 changes: 8 additions & 3 deletions lib/internal/test_runner/harness.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// https://github.com/nodejs/node/blob/1523a1817ed9b06fb51c0149451f9ea31bd2756e/lib/internal/test_runner/harness.js
// https://github.com/nodejs/node/blob/26e27424ad91c60a44d3d4c58b62a39b555ba75d/lib/internal/test_runner/harness.js
'use strict'
const {
ArrayPrototypeForEach,
Expand All @@ -14,8 +14,10 @@ const {
ERR_TEST_FAILURE
}
} = require('#internal/errors')
const { getOptionValue } = require('#internal/options')
const { Test, ItTest, Suite } = require('#internal/test_runner/test')

const isTestRunner = getOptionValue('--test')
const testResources = new SafeMap()
const root = new Test({ __proto__: null, name: '<root>' })
let wasRootSetup = false
Expand Down Expand Up @@ -136,8 +138,11 @@ function setup (root) {
process.on('uncaughtException', exceptionHandler)
process.on('unhandledRejection', rejectionHandler)
process.on('beforeExit', exitHandler)
process.on('SIGINT', terminationHandler)
process.on('SIGTERM', terminationHandler)
// TODO(MoLow): Make it configurable to hook when isTestRunner === false.
if (isTestRunner) {
process.on('SIGINT', terminationHandler)
process.on('SIGTERM', terminationHandler)
}

root.reporter.pipe(process.stdout)
root.reporter.version()
Expand Down
47 changes: 26 additions & 21 deletions lib/internal/test_runner/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// https://github.com/nodejs/node/blob/dab492f0444b0a6ae8a41dd1d9605e036c363655/lib/internal/test_runner/test.js
// https://github.com/nodejs/node/blob/a3e110820ff98702e1761831e7beaf0f5f1f75e7/lib/internal/test_runner/test.js

'use strict'

Expand Down Expand Up @@ -36,9 +36,9 @@ const {
} = require('#internal/util')
const { isPromise } = require('#internal/util/types')
const {
isUint32,
validateAbortSignal,
validateNumber
validateNumber,
validateUint32
} = require('#internal/validators')
const { setTimeout } = require('#timers/promises')
const { TIMEOUT_MAX } = require('#internal/timers')
Expand Down Expand Up @@ -152,14 +152,22 @@ 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, 'options.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) throw new TypeError(`Expected options.concurrency to be a number or boolean, got ${concurrency}`)
}

if (timeout != null && timeout !== Infinity) {
Expand Down Expand Up @@ -554,25 +562,22 @@ class Suite extends Test {

try {
const context = { signal: this.signal }
this.buildSuite = this.runInAsyncScope(this.fn, context, [context])
this.buildSuite = PromisePrototypeThen(
PromiseResolve(this.runInAsyncScope(this.fn, context, [context])),
undefined,
(err) => {
this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure))
})
} catch (err) {
this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure))
}
this.fn = () => {}
this.buildPhaseFinished = true
}

start () {
return this.run()
}

async run () {
try {
await this.buildSuite
} catch (err) {
this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure))
}
this.parent.activeSubtests++
await this.buildSuite
this.startTime = hrtime()

if (this[kShouldAbort]()) {
Expand Down
20 changes: 18 additions & 2 deletions lib/internal/validators.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// https://github.com/nodejs/node/blob/d83446b4c4694322e12d2b7d22592f2be674e580/lib/internal/validators.js
// https://github.com/nodejs/node/blob/60da0a1b364efdd84870269d23b39faa12fb46d8/lib/internal/validators.js
function isUint32 (value) {
return value === (value >>> 0)
}
Expand All @@ -23,8 +23,24 @@ const validateAbortSignal = (signal, name) => {
}
}

const validateUint32 = (value, name, positive) => {
if (typeof value !== 'number') {
throw new TypeError(`Expected ${name} to be a number, got ${value}`)
}
if (!Number.isInteger(value)) {
throw new RangeError(`Expected ${name} to be an integer, got ${value}`)
}
const min = positive ? 1 : 0
// 2 ** 32 === 4294967296
const max = 4_294_967_295
if (value < min || value > max) {
throw new RangeError(`Expected ${name} to be ${`>= ${min} && <= ${max}`}, got ${value}`)
}
}

module.exports = {
isUint32,
validateAbortSignal,
validateNumber
validateNumber,
validateUint32
}
4 changes: 3 additions & 1 deletion test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,7 @@ if (process.version.startsWith('v14.') || process.version.startsWith('v16.')) {
}

module.exports = {
expectsError
expectsError,
isWindow: process.platform === 'win32',
mustCall
}
7 changes: 7 additions & 0 deletions test/fixtures/test-runner/never_ending_async.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// https://github.com/nodejs/node/blob/26e27424ad91c60a44d3d4c58b62a39b555ba75d/test/fixtures/test-runner/never_ending_async.js
const test = require('#node:test')
const { setTimeout } = require('#timers/promises')

// We are using a very large timeout value to ensure that the parent process
// will have time to send a SIGINT signal to cancel the test.
test('never ending test', () => setTimeout(100_000_000))
6 changes: 6 additions & 0 deletions test/fixtures/test-runner/never_ending_sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// https://github.com/nodejs/node/blob/26e27424ad91c60a44d3d4c58b62a39b555ba75d/test/fixtures/test-runner/never_ending_sync.js
const test = require('#node:test')

test('never ending test', () => {
while (true);
})
58 changes: 45 additions & 13 deletions test/message/test_runner_desctibe_it.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// https://github.com/nodejs/node/blob/389b7e138e89a339fabe4ad628bf09cd9748f957/test/message/test_runner_desctibe_it.js
// https://github.com/nodejs/node/blob/a3e110820ff98702e1761831e7beaf0f5f1f75e7/test/message/test_runner_desctibe_it.js
// Flags: --no-warnings
'use strict'
require('../common')
Expand Down Expand Up @@ -149,18 +149,6 @@ describe('level 0a', { concurrency: 4 }, () => {
return p0a
})

describe('top level', { concurrency: 2 }, () => {
it('+long running', async () => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 3000).unref()
})
})

describe('+short running', async () => {
it('++short running', async () => {})
})
})

describe('invalid subtest - pass but subtest fails', () => {
setImmediate(() => {
it('invalid subtest fail', () => {
Expand Down Expand Up @@ -338,3 +326,47 @@ describe('timeouts', () => {
setTimeout(done, 10)
})
})

describe('successful thenable', () => {
it('successful thenable', () => {
let thenCalled = false
return {
get then () {
if (thenCalled) throw new Error()
thenCalled = true
return (successHandler) => successHandler()
}
}
})

it('rejected thenable', () => {
let thenCalled = false
return {
get then () {
if (thenCalled) throw new Error()
thenCalled = true
return (_, errorHandler) => errorHandler(new Error('custom error'))
}
}
})

let thenCalled = false
return {
get then () {
if (thenCalled) throw new Error()
thenCalled = true
return (successHandler) => successHandler()
}
}
})

describe('rejected thenable', () => {
let thenCalled = false
return {
get then () {
if (thenCalled) throw new Error()
thenCalled = true
return (_, errorHandler) => errorHandler(new Error('custom error'))
}
}
})
Loading