node-spec-runner.js 2.7 KB

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