node-spec-runner.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const minimist = require('minimist');
  2. const cp = require('node:child_process');
  3. const fs = require('node:fs');
  4. const path = require('node:path');
  5. const utils = require('./lib/utils');
  6. const DISABLED_TESTS = require('./node-disabled-tests.json');
  7. const args = minimist(process.argv.slice(2), {
  8. boolean: ['default', 'validateDisabled'],
  9. string: ['jUnitDir']
  10. });
  11. const BASE = path.resolve(__dirname, '../..');
  12. const NODE_DIR = path.resolve(BASE, 'third_party', 'electron_node');
  13. const JUNIT_DIR = args.jUnitDir ? path.resolve(args.jUnitDir) : null;
  14. const TAP_FILE_NAME = 'test.tap';
  15. if (!require.main) {
  16. throw new Error('Must call the node spec runner directly');
  17. }
  18. const defaultOptions = [
  19. 'tools/test.py',
  20. '-p',
  21. 'tap',
  22. '--logfile',
  23. TAP_FILE_NAME,
  24. '--mode=debug',
  25. 'default',
  26. `--skip-tests=${DISABLED_TESTS.join(',')}`,
  27. '--flaky-tests=dontcare',
  28. '--measure-flakiness=9',
  29. '--shell',
  30. utils.getAbsoluteElectronExec(),
  31. '-J'
  32. ];
  33. const getCustomOptions = () => {
  34. let customOptions = ['tools/test.py'];
  35. // Add all custom arguments.
  36. const extra = process.argv.slice(2);
  37. if (extra) {
  38. customOptions = customOptions.concat(extra);
  39. }
  40. // Necessary or Node.js will try to run from out/Release/node.
  41. customOptions = customOptions.concat([
  42. '--shell',
  43. utils.getAbsoluteElectronExec()
  44. ]);
  45. return customOptions;
  46. };
  47. async function main () {
  48. // Optionally validate that all disabled specs still exist.
  49. if (args.validateDisabled) {
  50. const missing = [];
  51. for (const test of DISABLED_TESTS) {
  52. const js = path.join(NODE_DIR, 'test', `${test}.js`);
  53. const mjs = path.join(NODE_DIR, 'test', `${test}.mjs`);
  54. if (!fs.existsSync(js) && !fs.existsSync(mjs)) {
  55. missing.push(test);
  56. }
  57. }
  58. if (missing.length > 0) {
  59. console.error(`Found ${missing.length} missing disabled specs: \n${missing.join('\n')}`);
  60. process.exit(1);
  61. }
  62. process.exit(0);
  63. }
  64. const options = args.default ? defaultOptions : getCustomOptions();
  65. const testChild = cp.spawn('python3', options, {
  66. env: {
  67. ...process.env,
  68. ELECTRON_RUN_AS_NODE: 'true',
  69. ELECTRON_EAGER_ASAR_HOOK_FOR_TESTING: 'true'
  70. },
  71. cwd: NODE_DIR,
  72. stdio: 'inherit'
  73. });
  74. testChild.on('exit', (testCode) => {
  75. if (JUNIT_DIR) {
  76. fs.mkdirSync(JUNIT_DIR);
  77. const converterStream = require('tap-xunit')();
  78. fs.createReadStream(
  79. path.resolve(NODE_DIR, TAP_FILE_NAME)
  80. ).pipe(converterStream).pipe(
  81. fs.createWriteStream(path.resolve(JUNIT_DIR, 'nodejs.xml'))
  82. ).on('close', () => {
  83. process.exit(testCode);
  84. });
  85. }
  86. });
  87. }
  88. main().catch((err) => {
  89. console.error('An unhandled error occurred in the node spec runner', err);
  90. process.exit(1);
  91. });