current commit
261023.16 · build,test: setup perfetto tests on windows build
'use strict';

// Helpers to deal with both Chrome legacy JSON trace format, and Perfetto
// binary format.
// This depends on perfetto's `trace_processor_shell` converts to pftrace format
// to JSON format. Run `make tools/perfetto/trace_processor_shell` to download
// it (`vcbuild test` does so on Windows), or point `TRACE_PROCESSOR_SHELL_PATH`
// at an existing build of it.

const assert = require('assert');
const { spawnSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const common = require('./');

const traceProcessor = path.resolve(
  __dirname, '..', '..',
  process.env.TRACE_PROCESSOR_SHELL_PATH ||
    `tools/perfetto/trace_processor_shell${common.isWindows ? '.exe' : ''}`);

// The JSON form of a trace runs about three times the size of the trace it was
// converted from, and the traces these tests produce are a few hundred KiB at
// most. This is an assumed MAX size of a JSON conversion size limit for tests.
const kMaxTraceJsonBytes = 64 * 1024 * 1024;

const traceFileExt = common.hasPerfetto ? 'pftrace' : 'log';
const defaultTraceFileName = `node_trace.1.${traceFileExt}`;

// Only perfetto traces need converting, so a missing `trace_processor_shell`
// does not stop anything on a legacy build.
function checkTraceProcessor() {
  if (common.hasPerfetto && !fs.existsSync(traceProcessor)) {
    assert.fail('trace_processor_shell is missing, ' +
                'run `python3 tools/perfetto/get_trace_processor.py` to download it');
  }
}

function readTraceEvents(file) {
  if (!common.hasPerfetto) {
    return JSON.parse(fs.readFileSync(file, 'utf8')).traceEvents;
  }

  const converted = spawnSync(traceProcessor, ['convert', 'json', file],
                              { maxBuffer: kMaxTraceJsonBytes });
  assert.ifError(converted.error);
  assert.strictEqual(
    converted.status, 0,
    `trace_processor_shell failed: ${converted.stderr}`);
  return JSON.parse(converted.stdout.toString()).traceEvents;
}

// A perfetto trace event carries the single category it was emitted with. The
// legacy backend instead groups it with every ancestor category, so
// `node.net.native` is recorded as `node,node.net,node.net.native`.
function traceCategory(name) {
  if (common.hasPerfetto) {
    return name;
  }
  const parts = name.split('.');
  return parts.map((_, i) => parts.slice(0, i + 1).join('.')).join(',');
}

module.exports = {
  defaultTraceFileName,
  readTraceEvents,
  checkTraceProcessor,
  traceCategory,
};