From 9d8616d955006a940f992fb0d8d794d8fb6eb661 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 24 Feb 2024 18:55:27 +0100 Subject: [PATCH] test: split wasi tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the child process code into a fixture and split the test so that it can be run in parallel and it's easier to identify where the failure is coming from. Also use the spawnSyncAndExitWithoutError() utility so that the test shows complete information on failure. Instead of marking all the wasi tests as flaky, only mark the wasi-poll one which is flaking in the CI now. PR-URL: https://github.com/nodejs/node/pull/51836 Refs: https://github.com/nodejs/node/issues/51822 Reviewed-By: Marco Ippolito Reviewed-By: Rich Trott Reviewed-By: Michaƫl Zasso --- test/common/wasi.js | 43 +++++++++ test/fixtures/wasi-preview-1.js | 48 ++++++++++ test/wasi/test-wasi-exitcode.js | 7 ++ test/wasi/test-wasi-io.js | 14 +++ test/wasi/test-wasi-poll.js | 5 ++ test/wasi/test-wasi.js | 149 +++++--------------------------- test/wasi/wasi.status | 2 +- 7 files changed, 141 insertions(+), 127 deletions(-) create mode 100644 test/common/wasi.js create mode 100644 test/fixtures/wasi-preview-1.js create mode 100644 test/wasi/test-wasi-exitcode.js create mode 100644 test/wasi/test-wasi-io.js create mode 100644 test/wasi/test-wasi-poll.js diff --git a/test/common/wasi.js b/test/common/wasi.js new file mode 100644 index 00000000000000..5c3cdc9bf4c652 --- /dev/null +++ b/test/common/wasi.js @@ -0,0 +1,43 @@ +// Test version set to preview1 +'use strict'; + +const { spawnSyncAndExitWithoutError } = require('./child_process'); +const fixtures = require('./fixtures'); +const childPath = fixtures.path('wasi-preview-1.js'); + +function testWasiPreview1(args, spawnArgs = {}, expectations = {}) { + const newEnv = { + ...process.env, + NODE_DEBUG_NATIVE: 'wasi', + NODE_PLATFORM: process.platform, + ...spawnArgs.env, + }; + spawnArgs.env = newEnv; + + console.log('Testing with --turbo-fast-api-calls:', ...args); + spawnSyncAndExitWithoutError( + process.execPath, [ + '--turbo-fast-api-calls', + childPath, + ...args, + ], + spawnArgs, + expectations, + ); + + console.log('Testing with --no-turbo-fast-api-calls:', ...args); + spawnSyncAndExitWithoutError( + process.execPath, + [ + '--no-turbo-fast-api-calls', + childPath, + ...args, + ], + spawnArgs, + expectations, + ); +} + +module.exports = { + testWasiPreview1, +}; diff --git a/test/fixtures/wasi-preview-1.js b/test/fixtures/wasi-preview-1.js new file mode 100644 index 00000000000000..3c11c6db1646bc --- /dev/null +++ b/test/fixtures/wasi-preview-1.js @@ -0,0 +1,48 @@ +'use strict'; + +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); +const fs = require('fs'); +const path = require('path'); +const common = require('../common'); +const { WASI } = require('wasi'); + +function returnOnExitEnvToValue(env) { + const envValue = env.RETURN_ON_EXIT; + if (envValue === undefined) { + return undefined; + } + + return envValue === 'true'; +} + +common.expectWarning('ExperimentalWarning', + 'WASI is an experimental feature and might change at any time'); + +tmpdir.refresh(); +const wasmDir = path.join(__dirname, '..', 'wasi', 'wasm'); +const wasiPreview1 = new WASI({ + version: 'preview1', + args: ['foo', '-bar', '--baz=value'], + env: process.env, + preopens: { + '/sandbox': fixtures.path('wasi'), + '/tmp': tmpdir.path, + }, + returnOnExit: returnOnExitEnvToValue(process.env), +}); + +// Validate the getImportObject helper +assert.strictEqual(wasiPreview1.wasiImport, + wasiPreview1.getImportObject().wasi_snapshot_preview1); +const modulePathPreview1 = path.join(wasmDir, `${process.argv[2]}.wasm`); +const bufferPreview1 = fs.readFileSync(modulePathPreview1); + +(async () => { + const { instance: instancePreview1 } = + await WebAssembly.instantiate(bufferPreview1, + wasiPreview1.getImportObject()); + + wasiPreview1.start(instancePreview1); +})().then(common.mustCall()); diff --git a/test/wasi/test-wasi-exitcode.js b/test/wasi/test-wasi-exitcode.js new file mode 100644 index 00000000000000..5fc0498e4be7d7 --- /dev/null +++ b/test/wasi/test-wasi-exitcode.js @@ -0,0 +1,7 @@ +'use strict'; +require('../common'); +const { testWasiPreview1 } = require('../common/wasi'); + +testWasiPreview1(['exitcode']); +testWasiPreview1(['exitcode'], { env: { RETURN_ON_EXIT: true } }); +testWasiPreview1(['exitcode'], { env: { RETURN_ON_EXIT: false } }, { status: 120 }); diff --git a/test/wasi/test-wasi-io.js b/test/wasi/test-wasi-io.js new file mode 100644 index 00000000000000..061ac88a73ece4 --- /dev/null +++ b/test/wasi/test-wasi-io.js @@ -0,0 +1,14 @@ +'use strict'; +const common = require('../common'); +const { checkoutEOL } = common; +const { testWasiPreview1 } = require('../common/wasi'); + +testWasiPreview1(['freopen'], {}, { stdout: `hello from input2.txt${checkoutEOL}` }); +testWasiPreview1(['read_file'], {}, { stdout: `hello from input.txt${checkoutEOL}` }); +testWasiPreview1(['read_file_twice'], {}, { + stdout: `hello from input.txt${checkoutEOL}hello from input.txt${checkoutEOL}`, +}); +// Tests that are currently unsupported on Windows. +if (!common.isWindows) { + testWasiPreview1(['stdin'], { input: 'hello world' }, { stdout: 'hello world' }); +} diff --git a/test/wasi/test-wasi-poll.js b/test/wasi/test-wasi-poll.js new file mode 100644 index 00000000000000..7448f626dca9b2 --- /dev/null +++ b/test/wasi/test-wasi-poll.js @@ -0,0 +1,5 @@ +'use strict'; +require('../common'); +const { testWasiPreview1 } = require('../common/wasi'); + +testWasiPreview1(['poll']); diff --git a/test/wasi/test-wasi.js b/test/wasi/test-wasi.js index f1f3ece4b4e1a6..9be57adc9d7360 100644 --- a/test/wasi/test-wasi.js +++ b/test/wasi/test-wasi.js @@ -1,131 +1,28 @@ 'use strict'; const common = require('../common'); - -function returnOnExitEnvToValue(env) { - const envValue = env.RETURN_ON_EXIT; - if (envValue === undefined) { - return undefined; - } - - return envValue === 'true'; +const { testWasiPreview1 } = require('../common/wasi'); + +// TODO(joyeecheung): tests that don't need special configurations can be ported +// to a special python test case configuration and get run in parallel. +// Tests that are currently unsupported on IBM i PASE. +if (!common.isIBMi) { + testWasiPreview1(['clock_getres']); + testWasiPreview1(['getrusage']); } -if (process.argv[2] === 'wasi-child-preview1') { - // Test version set to preview1 - const assert = require('assert'); - const fixtures = require('../common/fixtures'); - const tmpdir = require('../common/tmpdir'); - const fs = require('fs'); - const path = require('path'); - - common.expectWarning('ExperimentalWarning', - 'WASI is an experimental feature and might change at any time'); - - const { WASI } = require('wasi'); - tmpdir.refresh(); - const wasmDir = path.join(__dirname, 'wasm'); - const wasiPreview1 = new WASI({ - version: 'preview1', - args: ['foo', '-bar', '--baz=value'], - env: process.env, - preopens: { - '/sandbox': fixtures.path('wasi'), - '/tmp': tmpdir.path, - }, - returnOnExit: returnOnExitEnvToValue(process.env), - }); - - // Validate the getImportObject helper - assert.strictEqual(wasiPreview1.wasiImport, - wasiPreview1.getImportObject().wasi_snapshot_preview1); - const modulePathPreview1 = path.join(wasmDir, `${process.argv[3]}.wasm`); - const bufferPreview1 = fs.readFileSync(modulePathPreview1); - - (async () => { - const { instance: instancePreview1 } = - await WebAssembly.instantiate(bufferPreview1, - wasiPreview1.getImportObject()); - - wasiPreview1.start(instancePreview1); - })().then(common.mustCall()); -} else { - const assert = require('assert'); - const cp = require('child_process'); - const { checkoutEOL } = common; - - function innerRunWASI(options, args, flavor = 'preview1') { - console.log('executing', options.test); - const opts = { - env: { - ...process.env, - NODE_DEBUG_NATIVE: 'wasi', - NODE_PLATFORM: process.platform, - }, - }; - - if (options.stdin !== undefined) - opts.input = options.stdin; - - if ('returnOnExit' in options) { - opts.env.RETURN_ON_EXIT = options.returnOnExit; - } - - const child = cp.spawnSync(process.execPath, [ - ...args, - __filename, - 'wasi-child-' + flavor, - options.test, - ], opts); - console.log(child.stderr.toString()); - assert.strictEqual(child.status, options.exitCode || 0); - assert.strictEqual(child.signal, null); - assert.strictEqual(child.stdout.toString(), options.stdout || ''); - } - - function runWASI(options) { - innerRunWASI(options, ['--no-turbo-fast-api-calls']); - innerRunWASI(options, ['--turbo-fast-api-calls']); - } - - runWASI({ test: 'cant_dotdot' }); - - // Tests that are currently unsupported on IBM i PASE. - if (!common.isIBMi) { - runWASI({ test: 'clock_getres' }); - } - runWASI({ test: 'exitcode' }); - runWASI({ test: 'exitcode', returnOnExit: true }); - runWASI({ test: 'exitcode', exitCode: 120, returnOnExit: false }); - runWASI({ test: 'fd_prestat_get_refresh' }); - runWASI({ test: 'freopen', stdout: `hello from input2.txt${checkoutEOL}` }); - runWASI({ test: 'ftruncate' }); - runWASI({ test: 'getentropy' }); - - // Tests that are currently unsupported on IBM i PASE. - if (!common.isIBMi) { - runWASI({ test: 'getrusage' }); - } - runWASI({ test: 'gettimeofday' }); - runWASI({ test: 'main_args' }); - runWASI({ test: 'notdir' }); - runWASI({ test: 'poll' }); - runWASI({ test: 'preopen_populates' }); - - if (!common.isWindows && process.platform !== 'android') { - runWASI({ test: 'readdir' }); - } - - runWASI({ test: 'read_file', stdout: `hello from input.txt${checkoutEOL}` }); - runWASI({ - test: 'read_file_twice', - stdout: `hello from input.txt${checkoutEOL}hello from input.txt${checkoutEOL}`, - }); - runWASI({ test: 'stat' }); - runWASI({ test: 'sock' }); - runWASI({ test: 'write_file' }); - - // Tests that are currently unsupported on Windows. - if (!common.isWindows) { - runWASI({ test: 'stdin', stdin: 'hello world', stdout: 'hello world' }); - } +// Tests that are currently unsupported on Windows and Android. +if (!common.isWindows && process.platform !== 'android') { + testWasiPreview1(['readdir']); } + +testWasiPreview1(['cant_dotdot']); +testWasiPreview1(['fd_prestat_get_refresh']); +testWasiPreview1(['ftruncate']); +testWasiPreview1(['getentropy']); +testWasiPreview1(['gettimeofday']); +testWasiPreview1(['main_args']); +testWasiPreview1(['notdir']); +testWasiPreview1(['preopen_populates']); +testWasiPreview1(['stat']); +testWasiPreview1(['sock']); +testWasiPreview1(['write_file']); diff --git a/test/wasi/wasi.status b/test/wasi/wasi.status index 18792fc2ea3dd5..500040c0c2a037 100644 --- a/test/wasi/wasi.status +++ b/test/wasi/wasi.status @@ -9,4 +9,4 @@ prefix wasi # Windows on ARM [$system==win32 && $arch==arm64] # https://github.com/nodejs/node/issues/51822 -test-wasi: PASS, FLAKY +test-wasi-poll: PASS, FLAKY