test-helper.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. const { exec, spawn } = require('child_process');
  2. /**
  3. * wrap child_process.exec with retry. Will throw immediately when return
  4. * code not 0; Used for trivial commands since error detail won't be printed.
  5. * @param {string} command
  6. * @param {structure} execOptoins
  7. * @param {number} retryCount
  8. */
  9. async function executeCommand(command, execOptoins = {}, retryCount = 1) {
  10. try {
  11. const execCommand = command.join(' ');
  12. const { stderr, stdout } = await execute(execCommand, execOptoins);
  13. if (stderr) process.stderr.write(stderr.toString());
  14. if (stdout) process.stderr.write(stdout.toString());
  15. } catch (error) {
  16. if (retryCount > 0) {
  17. await executeCommand(command, execOptoins, --retryCount);
  18. } else {
  19. throw error;
  20. }
  21. }
  22. }
  23. function execute(command, options) {
  24. return new Promise((resolve, reject) => {
  25. exec(command, options, (err, stdout, stderr) => {
  26. if (err) {
  27. reject(err);
  28. } else {
  29. resolve({
  30. stdout: stdout,
  31. stderr: stderr
  32. });
  33. }
  34. });
  35. })
  36. }
  37. /**
  38. * wrap child_process.spawn with retry
  39. * @param {string} command
  40. * @param {structure} execOptions
  41. * @param {number} retryCount
  42. */
  43. async function executeLongProcessCommand(command, execOptions = {}, retryCount = 1) {
  44. try {
  45. const firstCommand = command[0];
  46. const options = command.slice(1);
  47. await promisifiedSpawn(firstCommand, options, execOptions);
  48. } catch (error) {
  49. if (retryCount > 0) {
  50. await executeLongProcessCommand(command, execOptions, --retryCount);
  51. } else {
  52. throw error;
  53. }
  54. }
  55. }
  56. function promisifiedSpawn(command, options, execOptions) {
  57. return new Promise((resolve, reject) => {
  58. const subProcess = spawn(command, options, execOptions);
  59. subProcess.stdout.on('data', (data) => {
  60. process.stdout.write(data.toString());
  61. });
  62. subProcess.stderr.on('data', (data) => {
  63. process.stderr.write(data.toString());
  64. });
  65. subProcess.on('error', (err) => {
  66. console.error('spawn error: ', err);
  67. });
  68. subProcess.on('close', (code) => {
  69. if (code === 0) {
  70. resolve();
  71. } else {
  72. reject(`"${command} ${options.join(' ')}" exited with code: ${code}`);
  73. }
  74. });
  75. });
  76. }
  77. module.exports = {
  78. execute: executeCommand,
  79. executeLongProcess: executeLongProcessCommand,
  80. }