test: move sea tests into test/sea

This makes skipping/running these tests easier to manage with a
dedicated test runner that can be tweaked for SEA.

PR-URL: https://github.com/nodejs/node/pull/60250
Refs: https://github.com/nodejs/node/issues/59553
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
This commit is contained in:
Joyee Cheung
2025-10-13 22:42:22 +02:00
parent c2f3c2131d
commit 64bbb979de
24 changed files with 105 additions and 107 deletions

View File

@@ -14,9 +14,6 @@ test-watch-mode-inspect: PASS, FLAKY
test-http2-large-file: PASS, FLAKY
[$system==win32]
# https://github.com/nodejs/node/issues/49630
test-single-executable-application-snapshot: PASS, FLAKY
test-single-executable-application-snapshot-and-code-cache: PASS, FLAKY
# https://github.com/nodejs/node/issues/47409
test-http2-large-file: PASS, FLAKY
@@ -26,27 +23,6 @@ test-http-server-request-timeouts-mixed: PASS, FLAKY
[$system==macos]
[$system==macos && $arch==x64]
# https://github.com/nodejs/node/issues/59553
test-single-executable-application: PASS, FLAKY
test-single-executable-application-assets: PASS, FLAKY
test-single-executable-application-assets-raw: PASS, FLAKY
test-single-executable-application-asset-keys-empty: PASS, FLAKY
test-single-executable-application-asset-keys: PASS, FLAKY
test-single-executable-application-disable-experimental-sea-warning: PASS, FLAKY
test-single-executable-application-empty: PASS, FLAKY
test-single-executable-application-exec-argv: PASS, FLAKY
test-single-executable-application-exec-argv-empty: PASS, FLAKY
test-single-executable-application-exec-argv-extension-cli: PASS, FLAKY
test-single-executable-application-exec-argv-extension-env: PASS, FLAKY
test-single-executable-application-exec-argv-extension-none: PASS, FLAKY
test-single-executable-application-inspect-in-sea-flags: PASS, FLAKY
test-single-executable-application-inspect: PASS, FLAKY
test-single-executable-application-snapshot: PASS, FLAKY
test-single-executable-application-snapshot-and-code-cache: PASS, FLAKY
test-single-executable-application-snapshot-worker: PASS, FLAKY
test-single-executable-application-use-code-cache: PASS, FLAKY
# https://github.com/nodejs/node/issues/43465
test-http-server-request-timeouts-mixed: PASS, FLAKY
@@ -70,24 +46,3 @@ test-tls-psk-client: PASS, FLAKY
[$arch==arm]
# https://github.com/nodejs/node/issues/49933
test-watch-mode-inspect: SKIP
[$system==linux && $arch==ppc64]
# https://github.com/nodejs/node/issues/59561
test-single-executable-application: SKIP
test-single-executable-application-assets: SKIP
test-single-executable-application-assets-raw: SKIP
test-single-executable-application-asset-keys-empty: SKIP
test-single-executable-application-asset-keys: SKIP
test-single-executable-application-disable-experimental-sea-warning: SKIP
test-single-executable-application-empty: SKIP
test-single-executable-application-exec-argv: SKIP
test-single-executable-application-exec-argv-empty: SKIP
test-single-executable-application-exec-argv-extension-cli: SKIP
test-single-executable-application-exec-argv-extension-env: SKIP
test-single-executable-application-exec-argv-extension-none: SKIP
test-single-executable-application-inspect-in-sea-flags: SKIP
test-single-executable-application-inspect: SKIP
test-single-executable-application-snapshot: SKIP
test-single-executable-application-snapshot-and-code-cache: SKIP
test-single-executable-application-snapshot-worker: SKIP
test-single-executable-application-use-code-cache: SKIP

View File

@@ -1,65 +0,0 @@
'use strict';
// This test verifies that the `getAssetKeys()` function works correctly
// in a single executable application without any assets.
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndExitWithoutError,
spawnSyncAndAssert,
} = require('../common/child_process');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset-keys.js'), tmpdir.resolve('sea.js'));
writeFileSync(tmpdir.resolve('sea-config.json'), `
{
"main": "sea.js",
"output": "sea-prep.blob"
}
`, 'utf8');
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
cwd: tmpdir.path
},
{});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /Asset keys: \[\]/,
}
);

View File

@@ -1,74 +0,0 @@
'use strict';
// This test verifies that the `getAssetKeys()` function works correctly
// in a single executable application with assets.
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndExitWithoutError,
spawnSyncAndAssert,
} = require('../common/child_process');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset-keys.js'), tmpdir.resolve('sea.js'));
writeFileSync(tmpdir.resolve('asset-1.txt'), 'This is asset 1');
writeFileSync(tmpdir.resolve('asset-2.txt'), 'This is asset 2');
writeFileSync(tmpdir.resolve('asset-3.txt'), 'This is asset 3');
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"assets": {
"asset-1.txt": "asset-1.txt",
"asset-2.txt": "asset-2.txt",
"asset-3.txt": "asset-3.txt"
}
}
`, 'utf8');
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
cwd: tmpdir.path
},
{});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /Asset keys: \["asset-1\.txt","asset-2\.txt","asset-3\.txt"\]/,
}
);

View File

@@ -1,70 +0,0 @@
'use strict';
const common = require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the snapshot support in single executable applications.
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndExitWithoutError,
} = require('../common/child_process');
const assert = require('assert');
const fixtures = require('../common/fixtures');
tmpdir.refresh();
if (!tmpdir.hasEnoughSpace(120 * 1024 * 1024)) {
common.skip('Not enough disk space');
}
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
{
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset-raw.js'), tmpdir.resolve('sea.js'));
copyFileSync(fixtures.path('person.jpg'), tmpdir.resolve('person.jpg'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"assets": {
"person.jpg": "person.jpg"
}
}
`, 'utf8');
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
cwd: tmpdir.path
});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndExitWithoutError(
outputFile,
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'SEA',
__TEST_PERSON_JPG: fixtures.path('person.jpg'),
}
},
);
}

View File

@@ -1,129 +0,0 @@
'use strict';
const common = require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the snapshot support in single executable applications.
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndAssert,
spawnSyncAndExit,
spawnSyncAndExitWithoutError,
} = require('../common/child_process');
const assert = require('assert');
const fixtures = require('../common/fixtures');
tmpdir.refresh();
if (!tmpdir.hasEnoughSpace(120 * 1024 * 1024)) {
common.skip('Not enough disk space');
}
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
{
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"assets": "invalid"
}
`);
spawnSyncAndExit(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path
},
{
status: 1,
signal: null,
stderr: /"assets" field of sea-config\.json is not a map of strings/
});
}
{
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"assets": {
"nonexistent": "nonexistent.txt"
}
}
`);
spawnSyncAndExit(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path
},
{
status: 1,
signal: null,
stderr: /Cannot read asset nonexistent\.txt: no such file or directory/
});
}
{
tmpdir.refresh();
copyFileSync(fixtures.path('sea', 'get-asset.js'), tmpdir.resolve('sea.js'));
copyFileSync(fixtures.utf8TestTextPath, tmpdir.resolve('utf8_test_text.txt'));
copyFileSync(fixtures.path('person.jpg'), tmpdir.resolve('person.jpg'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"assets": {
"utf8_test_text.txt": "utf8_test_text.txt",
"person.jpg": "person.jpg"
}
}
`, 'utf8');
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
cwd: tmpdir.path
});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'SEA',
__TEST_PERSON_JPG: fixtures.path('person.jpg'),
__TEST_UTF8_TEXT_PATH: fixtures.path('utf8_test_text.txt'),
}
},
{
trim: true,
stdout: fixtures.utf8TestText,
}
);
}

View File

@@ -1,67 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the creation of a single executable application which has the
// experimental SEA warning disabled.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const inputFile = fixtures.path('sea.js');
const requirableFile = tmpdir.resolve('requirable.js');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
writeFileSync(requirableFile, `
module.exports = {
hello: 'world',
};
`);
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true
}
`);
// Copy input to working directory
copyFileSync(inputFile, tmpdir.resolve('sea.js'));
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
[ '-a', '--b=c', 'd' ],
{
env: {
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
},
{
stdout: 'Hello, world! 😊\n'
});

View File

@@ -1,63 +0,0 @@
'use strict';
const common = require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the creation of a single executable application with an empty
// script.
const tmpdir = require('../common/tmpdir');
const { writeFileSync, existsSync } = require('fs');
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
writeFileSync(tmpdir.resolve('empty.js'), '', 'utf-8');
writeFileSync(configFile, `
{
"main": "empty.js",
"output": "sea-prep.blob"
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
// Verify the workflow.
try {
generateSEA(outputFile, process.execPath, seaPrepBlob, true);
} catch (e) {
if (/Cannot copy/.test(e.message)) {
common.skip(e.message);
} else if (common.isWindows) {
if (/Cannot sign/.test(e.message) || /Cannot find signtool/.test(e.message)) {
common.skip(e.message);
}
}
throw e;
}
spawnSyncAndExitWithoutError(
outputFile,
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
});

View File

@@ -1,61 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the execArgv functionality with empty array in single executable applications.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Copy test fixture to working directory
copyFileSync(fixtures.path('sea-exec-argv-empty.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true,
"execArgv": []
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Test that empty execArgv work correctly
spawnSyncAndAssert(
outputFile,
['user-arg'],
{
env: {
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
},
{
stdout: /empty execArgv test passed/
});

View File

@@ -1,63 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the execArgvExtension "cli" mode in single executable applications.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Copy test fixture to working directory
copyFileSync(fixtures.path('sea-exec-argv-extension-cli.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true,
"execArgv": ["--no-warnings"],
"execArgvExtension": "cli"
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Test that --node-options works with execArgvExtension: "cli"
spawnSyncAndAssert(
outputFile,
['--node-options=--max-old-space-size=1024', 'user-arg1', 'user-arg2'],
{
env: {
...process.env,
NODE_OPTIONS: '--max-old-space-size=2048', // Should be ignored
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /execArgvExtension cli test passed/
});

View File

@@ -1,68 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the execArgvExtension "env" mode (default) in single executable applications.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Copy test fixture to working directory
copyFileSync(fixtures.path('sea-exec-argv-extension-env.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true,
"execArgv": ["--no-warnings"],
"execArgvExtension": "env"
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Test that NODE_OPTIONS works with execArgvExtension: "env" (default behavior)
spawnSyncAndAssert(
outputFile,
['user-arg1', 'user-arg2'],
{
env: {
...process.env,
NODE_OPTIONS: '--max-old-space-size=512',
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /execArgvExtension env test passed/,
stderr(output) {
assert.doesNotMatch(output, /This warning should not be shown in the output/);
return true;
},
trim: true
});

View File

@@ -1,63 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the execArgvExtension "none" mode in single executable applications.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Copy test fixture to working directory
copyFileSync(fixtures.path('sea-exec-argv-extension-none.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true,
"execArgv": ["--no-warnings"],
"execArgvExtension": "none"
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Test that NODE_OPTIONS is ignored with execArgvExtension: "none"
spawnSyncAndAssert(
outputFile,
['user-arg1', 'user-arg2'],
{
env: {
...process.env,
NODE_OPTIONS: '--max-old-space-size=2048',
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /execArgvExtension none test passed/
});

View File

@@ -1,67 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the execArgv functionality with multiple arguments in single executable applications.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Copy test fixture to working directory
copyFileSync(fixtures.path('sea-exec-argv.js'), tmpdir.resolve('sea.js'));
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": true,
"execArgv": ["--no-warnings", "--max-old-space-size=2048"]
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Test that multiple execArgv are properly applied
spawnSyncAndAssert(
outputFile,
['user-arg1', 'user-arg2'],
{
env: {
...process.env,
NODE_NO_WARNINGS: '0',
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
}
},
{
stdout: /multiple execArgv test passed/,
stderr(output) {
assert.doesNotMatch(output, /This warning should not be shown in the output/);
return true;
},
trim: true,
});

View File

@@ -1,69 +0,0 @@
'use strict';
// This tests that the debugger flag --inspect passed directly to a single executable
// application would not be consumed by Node.js but passed to the application
// instead.
require('../common');
const assert = require('assert');
const { writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert } = require('../common/child_process');
const tmpdir = require('../common/tmpdir');
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
writeFileSync(tmpdir.resolve('sea.js'), `console.log(process.argv);`, 'utf-8');
// Create SEA configuration
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob"
}
`);
// Generate the SEA prep blob
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path }
);
assert(existsSync(seaPrepBlob));
// Generate the SEA executable
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Spawn the SEA with inspect option
spawnSyncAndAssert(
outputFile,
['--inspect=0'],
{
env: {
...process.env,
},
},
{
stdout(data) {
assert.match(data, /--inspect=0/);
return true;
},
stderr(data) {
assert.doesNotMatch(data, /Debugger listening/);
return true;
},
trim: true,
}
);

View File

@@ -1,122 +0,0 @@
'use strict';
// This tests the creation of a single executable application that can be
// debugged using the inspector protocol with NODE_OPTIONS=--inspect-brk=0
require('../common');
const assert = require('assert');
const { writeFileSync, existsSync } = require('fs');
const { spawn } = require('child_process');
const tmpdir = require('../common/tmpdir');
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
// Create a simple hello world script
writeFileSync(tmpdir.resolve('hello.js'), `console.log('Hello, world!');`, 'utf-8');
// Create SEA configuration
writeFileSync(configFile, `
{
"main": "hello.js",
"output": "sea-prep.blob"
}
`);
// Generate the SEA prep blob
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path }
);
assert(existsSync(seaPrepBlob));
// Generate the SEA executable
generateSEA(outputFile, process.execPath, seaPrepBlob);
// Spawn the SEA with inspect option
const seaProcess = spawn(outputFile, [], {
env: {
...process.env,
NODE_OPTIONS: '--inspect-brk=0',
},
});
let debuggerUrl = null;
let seaStderr = '';
seaProcess.stderr.setEncoding('utf8');
seaProcess.stdout.setEncoding('utf8');
seaProcess.stdout.on('data', (data) => {
console.log(`[SEA][STDOUT] ${data}`);
});
seaProcess.stderr.on('data', (data) => {
console.log(`[SEA][STDERR] ${data}`);
seaStderr += data;
// Parse the debugger listening message
const match = seaStderr.match(/Debugger listening on ws:\/\/([\d.]+):(\d+)\//);
if (match && !debuggerUrl) {
const host = match[1];
const port = match[2];
debuggerUrl = `${host}:${port}`;
console.log(`Running ${process.execPath} inspect ${debuggerUrl}`);
// Once we have the debugger URL, spawn the inspector CLI
const inspectorProcess = spawn(process.execPath, ['inspect', debuggerUrl], {
stdio: ['pipe', 'pipe', 'pipe'],
});
let inspectorStdout = '';
inspectorProcess.stdout.setEncoding('utf8');
inspectorProcess.stderr.setEncoding('utf8');
inspectorProcess.stdout.on('data', (data) => {
console.log(`[INSPECT][STDOUT] ${data}`);
inspectorStdout += data;
// Check if we successfully connected
const matches = [...inspectorStdout.matchAll(/debug> /g)];
if (inspectorStdout.includes(`connecting to ${host}:${port} ... ok`) &&
matches.length >= 2) {
// We are at the second prompt, which means we can send commands to terminate both now.
console.log('Sending .exit command to inspector...');
inspectorProcess.stdin.write('.exit\n');
}
});
inspectorProcess.stderr.on('data', (data) => {
console.log(`[INSPECT][STDERR] ${data}`);
});
inspectorProcess.on('close', (code) => {
assert.strictEqual(code, 0, `Inspector process exited with code ${code}.`);
});
inspectorProcess.on('error', (err) => {
throw err;
});
}
});
seaProcess.on('close', (code) => {
assert.strictEqual(code, 0, `SEA process exited with code ${code}.`);
});
seaProcess.on('error', (err) => {
throw err;
});

View File

@@ -1,78 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests "useCodeCache" is ignored when "useSnapshot" is true.
const tmpdir = require('../common/tmpdir');
const { writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndAssert,
} = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const configFile = join(tmpdir.path, 'sea-config.json');
const seaPrepBlob = join(tmpdir.path, 'sea-prep.blob');
const outputFile = join(tmpdir.path, process.platform === 'win32' ? 'sea.exe' : 'sea');
{
tmpdir.refresh();
const code = `
const {
setDeserializeMainFunction,
} = require('v8').startupSnapshot;
setDeserializeMainFunction(() => {
console.log('Hello from snapshot');
});
`;
writeFileSync(join(tmpdir.path, 'snapshot.js'), code, 'utf-8');
writeFileSync(configFile, `
{
"main": "snapshot.js",
"output": "sea-prep.blob",
"useSnapshot": true,
"useCodeCache": true
}
`);
spawnSyncAndAssert(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path,
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
},
{
stderr: /"useCodeCache" is redundant when "useSnapshot" is true/
}
);
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
NODE_DEBUG_NATIVE: 'SEA,MKSNAPSHOT',
...process.env,
}
}, {
stdout: 'Hello from snapshot',
trim: true,
});
}

View File

@@ -1,80 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the snapshot support in single executable applications.
const tmpdir = require('../common/tmpdir');
const { writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndAssert, spawnSyncAndExitWithoutError,
} = require('../common/child_process');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
{
tmpdir.refresh();
// FIXME(joyeecheung): currently `worker_threads` cannot be loaded during the
// snapshot building process because internal/worker.js is accessing isMainThread at
// the top level (and there are maybe more code that access these at the top-level),
// and have to be loaded in the deserialized snapshot main function.
// Change these states to be accessed on-demand.
const code = `
const {
setDeserializeMainFunction,
} = require('v8').startupSnapshot;
setDeserializeMainFunction(() => {
const { Worker } = require('worker_threads');
new Worker("console.log('Hello from Worker')", { eval: true });
});
`;
writeFileSync(tmpdir.resolve('snapshot.js'), code, 'utf-8');
writeFileSync(configFile, `
{
"main": "snapshot.js",
"output": "sea-prep.blob",
"useSnapshot": true
}
`);
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path,
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
},
{
trim: true,
stdout: 'Hello from Worker'
}
);
}

View File

@@ -1,108 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the snapshot support in single executable applications.
const tmpdir = require('../common/tmpdir');
const { writeFileSync, existsSync } = require('fs');
const {
spawnSyncAndAssert,
spawnSyncAndExit,
} = require('../common/child_process');
const assert = require('assert');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
{
tmpdir.refresh();
writeFileSync(tmpdir.resolve('snapshot.js'), '', 'utf-8');
writeFileSync(configFile, `
{
"main": "snapshot.js",
"output": "sea-prep.blob",
"useSnapshot": true
}
`);
spawnSyncAndExit(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path
},
{
status: 1,
signal: null,
stderr: /snapshot\.js does not invoke v8\.startupSnapshot\.setDeserializeMainFunction\(\)/
});
}
{
tmpdir.refresh();
const code = `
const {
setDeserializeMainFunction,
} = require('v8').startupSnapshot;
setDeserializeMainFunction(() => {
console.log('Hello from snapshot');
});
`;
writeFileSync(tmpdir.resolve('snapshot.js'), code, 'utf-8');
writeFileSync(configFile, `
{
"main": "snapshot.js",
"output": "sea-prep.blob",
"useSnapshot": true
}
`);
spawnSyncAndAssert(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path,
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
},
{
stderr: /Single executable application is an experimental feature/
});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
{
env: {
NODE_DEBUG_NATIVE: 'SEA,MKSNAPSHOT',
...process.env,
}
},
{
trim: true,
stdout: 'Hello from snapshot',
stderr(output) {
assert.doesNotMatch(
output,
/Single executable application is an experimental feature/);
}
}
);
}

View File

@@ -1,73 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the creation of a single executable application which uses the
// V8 code cache.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const inputFile = fixtures.path('sea.js');
const requirableFile = tmpdir.resolve('requirable.js');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
writeFileSync(requirableFile, `
module.exports = {
hello: 'world',
};
`);
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"useCodeCache": true
}
`);
// Copy input to working directory
copyFileSync(inputFile, tmpdir.resolve('sea.js'));
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{
cwd: tmpdir.path,
env: {
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
},
});
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
[ '-a', '--b=c', 'd' ],
{
env: {
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
},
{
stdout: 'Hello, world! 😊\n'
});

View File

@@ -1,66 +0,0 @@
'use strict';
require('../common');
const {
generateSEA,
skipIfSingleExecutableIsNotSupported,
} = require('../common/sea');
skipIfSingleExecutableIsNotSupported();
// This tests the creation of a single executable application.
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { copyFileSync, writeFileSync, existsSync } = require('fs');
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process');
const { join } = require('path');
const assert = require('assert');
const inputFile = fixtures.path('sea.js');
const requirableFile = tmpdir.resolve('requirable.js');
const configFile = tmpdir.resolve('sea-config.json');
const seaPrepBlob = tmpdir.resolve('sea-prep.blob');
const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'sea');
tmpdir.refresh();
writeFileSync(requirableFile, `
module.exports = {
hello: 'world',
};
`);
writeFileSync(configFile, `
{
"main": "sea.js",
"output": "sea-prep.blob",
"disableExperimentalSEAWarning": false
}
`);
// Copy input to working directory
copyFileSync(inputFile, tmpdir.resolve('sea.js'));
spawnSyncAndExitWithoutError(
process.execPath,
['--experimental-sea-config', 'sea-config.json'],
{ cwd: tmpdir.path });
assert(existsSync(seaPrepBlob));
generateSEA(outputFile, process.execPath, seaPrepBlob);
spawnSyncAndAssert(
outputFile,
[ '-a', '--b=c', 'd' ],
{
env: {
COMMON_DIRECTORY: join(__dirname, '..', 'common'),
NODE_DEBUG_NATIVE: 'SEA',
...process.env,
}
},
{
stdout: 'Hello, world! 😊\n'
});