jsSelfProfiling.spec.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {resolveJSSelfProfilingStack} from 'sentry/utils/profiling/jsSelfProfiling';
  2. import {createFrameIndex} from 'sentry/utils/profiling/profile/utils';
  3. const toStackNames = (stack: ReadonlyArray<JSSelfProfiling.Frame>): string[] => {
  4. return stack.map(f => f.name);
  5. };
  6. describe('jsSelfProfiling', () => {
  7. describe('resolveJSSelfProfilingStack', () => {
  8. it('when thread is idle and sample has no associated stackId', () => {
  9. const trace: JSSelfProfiling.Trace = {
  10. frames: [],
  11. resources: [],
  12. samples: [{stackId: undefined, timestamp: 0}],
  13. stacks: [],
  14. };
  15. expect(resolveJSSelfProfilingStack(trace, undefined, {})).toEqual([]);
  16. });
  17. it('when stackId is set', () => {
  18. const trace: JSSelfProfiling.Trace = {
  19. frames: [
  20. {name: 'foo', line: 0, column: 0},
  21. {name: 'bar', line: 0, column: 0},
  22. {name: 'baz', line: 0, column: 0},
  23. {name: 'foobar', line: 0, column: 0},
  24. {name: 'foobarbaz', line: 0, column: 0},
  25. {name: 'foobarbazfoo', line: 0, column: 0},
  26. ],
  27. resources: [],
  28. samples: [{stackId: 5, timestamp: 0}],
  29. stacks: [
  30. {frameId: 0, parentId: undefined},
  31. {frameId: 1, parentId: undefined},
  32. {frameId: 2, parentId: undefined},
  33. {frameId: 3, parentId: 2},
  34. {frameId: 4, parentId: 3},
  35. {frameId: 5, parentId: 4},
  36. ],
  37. };
  38. expect(
  39. toStackNames(
  40. resolveJSSelfProfilingStack(trace, 5, createFrameIndex('web', trace.frames))
  41. )
  42. ).toEqual(['baz', 'foobar', 'foobarbaz', 'foobarbazfoo']);
  43. });
  44. it('when marker is present on the stack', () => {
  45. const trace: JSSelfProfiling.Trace = {
  46. frames: [
  47. {name: 'foo', line: 0, column: 0},
  48. {name: 'bar', line: 0, column: 0},
  49. {name: 'baz', line: 0, column: 0},
  50. {name: 'foobar', line: 0, column: 0},
  51. {name: 'foobarbaz', line: 0, column: 0},
  52. {name: 'foobarbazfoo', line: 0, column: 0},
  53. ],
  54. resources: [],
  55. samples: [{stackId: 5, timestamp: 0, marker: 'gc'}],
  56. stacks: [
  57. {frameId: 0, parentId: undefined},
  58. {frameId: 1, parentId: undefined},
  59. {frameId: 2, parentId: undefined},
  60. {frameId: 3, parentId: 2},
  61. {frameId: 4, parentId: 3},
  62. {frameId: 5, parentId: 4},
  63. ],
  64. };
  65. // I'm not sure I like passing the marker, the reason it's like this is that we usually loop through the samples and have the marker as
  66. // we execute resolveJSSelfProfilingStack, but I'm not sure we should do that and instead augment the resolved stack outside of the loop.
  67. // The nice thing about it is that it centralizes the stack logic and makes it easier to test.
  68. expect(
  69. toStackNames(
  70. resolveJSSelfProfilingStack(
  71. trace,
  72. 5,
  73. createFrameIndex('web', trace.frames),
  74. 'gc'
  75. )
  76. )
  77. ).toEqual(['baz', 'foobar', 'foobarbaz', 'foobarbazfoo', 'Garbage Collection']);
  78. });
  79. it('when stack is empty, but browser was performing other operations', () => {
  80. const trace: JSSelfProfiling.Trace = {
  81. frames: [],
  82. resources: [],
  83. samples: [{stackId: 0, timestamp: 0, marker: 'paint'}],
  84. stacks: [{frameId: 0, parentId: undefined}],
  85. };
  86. expect(
  87. toStackNames(
  88. resolveJSSelfProfilingStack(
  89. trace,
  90. 0,
  91. createFrameIndex('web', trace.frames),
  92. 'paint'
  93. )
  94. )
  95. ).toEqual(['Paint']);
  96. });
  97. });
  98. });