common.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict';
  2. var path = require('path');
  3. var yaml = require('js-yaml');
  4. module.exports.getDiag = function (body, includeStack) {
  5. var yamlStart = body.indexOf(' ---');
  6. var yamlEnd = body.indexOf(' ...\n');
  7. var diag = body.slice(yamlStart, yamlEnd).split('\n').map(function (line) {
  8. return line.slice(2);
  9. }).join('\n');
  10. // The stack trace and at variable will vary depending on where the code
  11. // is run, so just strip it out.
  12. var withStack = yaml.safeLoad(diag);
  13. if (!includeStack) {
  14. delete withStack.stack;
  15. }
  16. delete withStack.at;
  17. return withStack;
  18. };
  19. // There are three challenges associated with checking the stack traces included
  20. // in errors:
  21. // 1) The base checkout directory of tape might change. Because stack traces
  22. // include absolute paths, the stack traces will change depending on the
  23. // checkout path. We handle this by replacing the base test directory with a
  24. // placeholder $TEST variable and the package root with a placeholder
  25. // $TAPE variable.
  26. // 2) Line positions within the file might change. We handle this by replacing
  27. // line and column markers with placeholder $LINE and $COL "variables"
  28. // a) node 0.8 does not provide nested eval line numbers, so we remove them
  29. // 3) Stacks themselves change frequently with refactoring. We've even run into
  30. // issues with node library refactorings "breaking" stack traces. Most of
  31. // these changes are irrelevant to the tests themselves. To counter this, we
  32. // strip out all stack frames that aren't directly under our test directory,
  33. // and replace them with placeholders.
  34. var stripChangingData = function (line) {
  35. var withoutTestDir = line.replace(__dirname, '$TEST');
  36. var withoutPackageDir = withoutTestDir.replace(path.dirname(__dirname), '$TAPE');
  37. var withoutPathSep = withoutPackageDir.replace(new RegExp('\\' + path.sep, 'g'), '/');
  38. var withoutLineNumbers = withoutPathSep.replace(/:\d+:\d+/g, ':$LINE:$COL');
  39. var withoutNestedLineNumbers = withoutLineNumbers.replace(/, <anonymous>:\$LINE:\$COL\)$/, ')');
  40. return withoutNestedLineNumbers;
  41. };
  42. module.exports.stripFullStack = function (output) {
  43. var stripped = ' [... stack stripped ...]';
  44. var withDuplicates = output.split(/\r?\n/g).map(stripChangingData).map(function (line) {
  45. var m = line.match(/[ ]{8}at .*\((.*)\)/);
  46. if (m && m[1].slice(0, 5) !== '$TEST') {
  47. return stripped;
  48. }
  49. return line;
  50. });
  51. var withoutInternals = withDuplicates.filter(function (line) {
  52. return !line.match(/ \(node:[^)]+\)$/);
  53. });
  54. var deduped = withoutInternals.filter(function (line, ix) {
  55. var hasPrior = line === stripped && withDuplicates[ix - 1] === stripped;
  56. return !hasPrior;
  57. });
  58. return deduped.join('\n').replace(
  59. // Handle stack trace variation in Node v0.8
  60. /at(:?) Test\.(?:module\.exports|tap\.test\.err\.code)/g,
  61. 'at$1 Test.<anonymous>'
  62. ).replace(
  63. // Handle stack trace variation in Node v0.8
  64. /at(:?) (Test\.)?tap\.test\.test\.skip/g,
  65. 'at$1 $2<anonymous>'
  66. ).replace(
  67. // Handle stack trace variation in Node v0.8
  68. /(\[\.\.\. stack stripped \.\.\.\]\r?\n *at) <anonymous> \(([^)]+)\)/g,
  69. '$1 $2'
  70. ).split(/\r?\n/g);
  71. };