Skip to content

Commit 126bad1

Browse files
committed
test: enable trace_events tests with perfetto
Signed-off-by: Chengzhong Wu <cwu631@bloomberg.net>
1 parent efc612d commit 126bad1

43 files changed

Lines changed: 604 additions & 365 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-shared.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ on:
2727
required: false
2828
type: boolean
2929
default: false
30+
perfetto:
31+
description: Whether the build links perfetto, which the trace event tests need trace_processor_shell for.
32+
required: false
33+
type: boolean
34+
default: false
3035
secrets:
3136
CACHIX_AUTH_TOKEN:
3237
description: Cachix auth token for nodejs.cachix.org.
@@ -78,6 +83,11 @@ jobs:
7883
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
7984
core.exportVariable('NIX_SCCACHE', '(import <nixpkgs> {}).sccache');
8085
86+
- name: Get trace_processor
87+
if: inputs.perfetto
88+
shell: bash
89+
run: make -C "$TAR_DIR" trace-processor
90+
8191
- name: Build Node.js and run tests
8292
shell: bash
8393
run: |

.github/workflows/test-linux-perfetto.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ jobs:
6262
- name: Build
6363
working-directory: node
6464
run: make build-ci -j4 V=1 CONFIG_FLAGS="--error-on-warn --v8-enable-temporal-support --with-perfetto"
65+
- name: Get trace_processor
66+
working-directory: node
67+
run: make trace-processor
6568
- name: Test
6669
working-directory: node
6770
run: make test-ci -j1 V=1 TEST_CI_ARGS="-p actions --measure-flakiness 9"

.github/workflows/test-shared.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ jobs:
163163
with:
164164
runner: ${{ matrix.runner }}
165165
with-sccache: ${{ github.base_ref == 'main' || github.ref_name == 'main' }}
166+
perfetto: ${{ matrix.perfetto || false }}
166167
extra-nix-flags: |
167168
--arg useSeparateDerivationForV8 true \
168169
${{ matrix.perfetto && '--arg withPerfetto true \' || '\' }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ tools/*/*.i.tmp
116116
/tools/eslint/node_modules
117117
/tools/lint-md/node_modules
118118

119+
# === Rules for tools/perfetto ===
120+
/tools/perfetto/trace_processor_shell
121+
/tools/perfetto/.version
122+
119123
# === Rules for test artifacts ===
120124
/*.tap
121125
/*.xml

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ distclean: ## Remove all build and test artifacts.
235235
$(RM) -r node_modules
236236
$(RM) -r deps/icu
237237
$(RM) -r deps/icu4c*.tgz deps/icu4c*.zip deps/icu-tmp
238+
$(RM) tools/perfetto/trace_processor_shell tools/perfetto/.version
238239
$(RM) $(BINARYTAR).* $(TARBALL).*
239240

240241
.PHONY: check
@@ -338,6 +339,10 @@ coverage-run-js: ## Run JavaScript tests with coverage.
338339
TEST_CI_ARGS="$(TEST_CI_ARGS) --type=coverage" $(MAKE) jstest
339340
$(MAKE) coverage-report-js
340341

342+
.PHONY: trace-processor
343+
trace-processor: ## Download perfetto's trace_processor_shell.
344+
@tools/perfetto/get_trace_processor
345+
341346
.PHONY: test
342347
# This does not run tests of third-party libraries inside deps.
343348
test: all ## Run default tests and build docs.
@@ -1319,7 +1324,7 @@ ifeq ($(SKIP_SHARED_DEPS), 1)
13191324
$(RM) -r $(TARNAME)/deps/ngtcp2
13201325
find $(TARNAME)/deps/openssl -maxdepth 1 -type f ! -name 'nodejs-openssl.cnf' -exec $(RM) {} +
13211326
find $(TARNAME)/deps/openssl -mindepth 1 -maxdepth 1 -type d -exec $(RM) -r {} +
1322-
$(RM) -r $(TARNAME)/deps/perfetto
1327+
find $(TARNAME)/deps/perfetto -mindepth 1 -maxdepth 1 ! -name 'VERSION' -exec $(RM) -r {} +
13231328
$(RM) -r $(TARNAME)/deps/simdjson
13241329
$(RM) -r $(TARNAME)/deps/sqlite
13251330
$(RM) -r $(TARNAME)/deps/uv

test/common/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ const common = {
10291029
hasSQLite,
10301030
hasFFI,
10311031
hasLocalStorage,
1032+
hasPerfetto,
10321033
invalidArgTypeHelper,
10331034
isAlive,
10341035
isASan,

test/common/trace_events.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
3+
// Helpers to deal with both Chrome legacy JSON trace format, and Perfetto
4+
// binary format.
5+
// This depends on perfetto's `trace_processor_shell` converts to pftrace format
6+
// to JSON format. Run `make trace-processor` to download it.
7+
8+
const assert = require('assert');
9+
const { spawnSync } = require('child_process');
10+
const fs = require('fs');
11+
const path = require('path');
12+
const common = require('./');
13+
14+
const traceProcessor = path.resolve(
15+
__dirname, '..', '..', 'tools', 'perfetto', 'trace_processor_shell');
16+
17+
// The JSON form of a trace runs about three times the size of the trace it was
18+
// converted from, and the traces these tests produce are a few hundred KiB at
19+
// most. This is an assumed MAX size of a JSON conversion size limit for tests.
20+
const kMaxTraceJsonBytes = 64 * 1024 * 1024;
21+
22+
const traceFileExt = common.hasPerfetto ? 'pftrace' : 'log';
23+
const defaultTraceFileName = `node_trace.1.${traceFileExt}`;
24+
25+
// Only perfetto traces need converting, so a missing `trace_processor_shell`
26+
// does not stop anything on a legacy build.
27+
function checkTraceProcessor() {
28+
if (common.hasPerfetto && !fs.existsSync(traceProcessor)) {
29+
assert.fail('trace_processor_shell is missing, ' +
30+
'run `make trace-processor` to download it');
31+
}
32+
}
33+
34+
function readTraceEvents(file) {
35+
if (!common.hasPerfetto) {
36+
return JSON.parse(fs.readFileSync(file, 'utf8')).traceEvents;
37+
}
38+
39+
const converted = spawnSync(traceProcessor, ['convert', 'json', file],
40+
{ maxBuffer: kMaxTraceJsonBytes });
41+
assert.ifError(converted.error);
42+
assert.strictEqual(
43+
converted.status, 0,
44+
`trace_processor_shell failed: ${converted.stderr}`);
45+
return JSON.parse(converted.stdout.toString()).traceEvents;
46+
}
47+
48+
// A perfetto trace event carries the single category it was emitted with. The
49+
// legacy backend instead groups it with every ancestor category, so
50+
// `node.net.native` is recorded as `node,node.net,node.net.native`.
51+
function traceCategory(name) {
52+
if (common.hasPerfetto) {
53+
return name;
54+
}
55+
const parts = name.split('.');
56+
return parts.map((_, i) => parts.slice(0, i + 1).join('.')).join(',');
57+
}
58+
59+
module.exports = {
60+
defaultTraceFileName,
61+
readTraceEvents,
62+
checkTraceProcessor,
63+
traceCategory,
64+
};

test/parallel/test-inspector-tracing-domain.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
const common = require('../common');
44

55
common.skipIfInspectorDisabled();
6+
// The inspector NodeTracing domain is not wired up on a perfetto build, see
7+
// src/inspector_agent.cc, so every command here fails with
8+
// ERR_INSPECTOR_COMMAND.
69
common.skipIfPerfettoEnabled();
710

811
const { isMainThread } = require('worker_threads');

test/parallel/test-module-print-timing.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import tmpdir from '../common/tmpdir.js';
77
import { spawnSyncAndAssert } from '../common/child_process.js';
88
import fixtures from '../common/fixtures.js';
99

10+
// The dynamic tracing case below records nothing on a perfetto build: a
11+
// category enabled after the tracing session started stays off.
1012
skipIfPerfettoEnabled();
1113
tmpdir.refresh();
1214

test/parallel/test-permission-fs-write-trace-events.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
// Flags: --expose-internals
21
'use strict';
32

43
const common = require('../common');
54
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
65
const { isMainThread } = require('worker_threads');
76

8-
common.skipIfPerfettoEnabled();
97
if (!isMainThread) {
108
common.skip('This test only works on a main thread');
119
}
1210

1311
const assert = require('assert');
1412
const fs = require('fs');
1513
const tmpdir = require('../common/tmpdir');
14+
const { defaultTraceFileName } = require('../common/trace_events');
1615

1716
try {
1817
require('trace_events');
@@ -56,7 +55,7 @@ assert.throws(() => {
5655
}, common.expectsError({
5756
code: 'ERR_ACCESS_DENIED',
5857
permission: 'FileSystemWrite',
59-
resource: 'node_trace.1.log',
58+
resource: defaultTraceFileName,
6059
}));
6160

62-
assert.strictEqual(fs.existsSync('node_trace.1.log'), false);
61+
assert.strictEqual(fs.existsSync(defaultTraceFileName), false);

0 commit comments

Comments
 (0)