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