11cb0ef41Sopenharmony_ci// Flags: --expose-gc --no-warnings --expose-internals 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst common = require('../common'); 51cb0ef41Sopenharmony_cicommon.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_citry { 81cb0ef41Sopenharmony_ci require('trace_events'); 91cb0ef41Sopenharmony_ci} catch { 101cb0ef41Sopenharmony_ci common.skip('missing trace events'); 111cb0ef41Sopenharmony_ci} 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciconst assert = require('assert'); 141cb0ef41Sopenharmony_ciconst cp = require('child_process'); 151cb0ef41Sopenharmony_ciconst path = require('path'); 161cb0ef41Sopenharmony_ciconst fs = require('fs'); 171cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir'); 181cb0ef41Sopenharmony_ciconst { 191cb0ef41Sopenharmony_ci createTracing, 201cb0ef41Sopenharmony_ci getEnabledCategories 211cb0ef41Sopenharmony_ci} = require('trace_events'); 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cifunction getEnabledCategoriesFromCommandLine() { 241cb0ef41Sopenharmony_ci const indexOfCatFlag = process.execArgv.indexOf('--trace-event-categories'); 251cb0ef41Sopenharmony_ci if (indexOfCatFlag === -1) { 261cb0ef41Sopenharmony_ci return undefined; 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci return process.execArgv[indexOfCatFlag + 1]; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciconst isChild = process.argv[2] === 'child'; 321cb0ef41Sopenharmony_ciconst enabledCategories = getEnabledCategoriesFromCommandLine(); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciassert.strictEqual(getEnabledCategories(), enabledCategories); 351cb0ef41Sopenharmony_ci[1, 'foo', true, false, null, undefined].forEach((i) => { 361cb0ef41Sopenharmony_ci assert.throws(() => createTracing(i), { 371cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 381cb0ef41Sopenharmony_ci name: 'TypeError' 391cb0ef41Sopenharmony_ci }); 401cb0ef41Sopenharmony_ci assert.throws(() => createTracing({ categories: i }), { 411cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 421cb0ef41Sopenharmony_ci name: 'TypeError' 431cb0ef41Sopenharmony_ci }); 441cb0ef41Sopenharmony_ci}); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciassert.throws( 471cb0ef41Sopenharmony_ci () => createTracing({ categories: [] }), 481cb0ef41Sopenharmony_ci { 491cb0ef41Sopenharmony_ci code: 'ERR_TRACE_EVENTS_CATEGORY_REQUIRED', 501cb0ef41Sopenharmony_ci name: 'TypeError' 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ciconst tracing = createTracing({ categories: [ 'node.perf' ] }); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ciassert.strictEqual(tracing.categories, 'node.perf'); 571cb0ef41Sopenharmony_ciassert.strictEqual(tracing.enabled, false); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciassert.strictEqual(getEnabledCategories(), enabledCategories); 601cb0ef41Sopenharmony_citracing.enable(); 611cb0ef41Sopenharmony_citracing.enable(); // Purposefully enable twice to test calling twice 621cb0ef41Sopenharmony_ciassert.strictEqual(tracing.enabled, true); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ciassert.strictEqual(getEnabledCategories(), 651cb0ef41Sopenharmony_ci [ 661cb0ef41Sopenharmony_ci ...[enabledCategories].filter((_) => !!_), 'node.perf', 671cb0ef41Sopenharmony_ci ].join(',')); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_citracing.disable(); 701cb0ef41Sopenharmony_ciassert.strictEqual(tracing.enabled, false); 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciconst tracing2 = createTracing({ categories: [ 'foo' ] }); 731cb0ef41Sopenharmony_citracing2.enable(); 741cb0ef41Sopenharmony_ciassert.strictEqual(getEnabledCategories(), 'foo'); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_citracing2.disable(); 771cb0ef41Sopenharmony_citracing2.disable(); // Purposefully disable twice to test calling twice 781cb0ef41Sopenharmony_ciassert.strictEqual(getEnabledCategories(), enabledCategories); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ciif (isChild) { 811cb0ef41Sopenharmony_ci const { internalBinding } = require('internal/test/binding'); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci const { 841cb0ef41Sopenharmony_ci trace: { 851cb0ef41Sopenharmony_ci TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent, 861cb0ef41Sopenharmony_ci TRACE_EVENT_PHASE_NESTABLE_ASYNC_END: kEndEvent, 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci } = internalBinding('constants'); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci const { trace } = internalBinding('trace_events'); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci tracing.enable(); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci trace(kBeforeEvent, 'foo', 'test1', 0, 'test'); 951cb0ef41Sopenharmony_ci setTimeout(() => { 961cb0ef41Sopenharmony_ci trace(kEndEvent, 'foo', 'test1'); 971cb0ef41Sopenharmony_ci }, 1); 981cb0ef41Sopenharmony_ci} else { 991cb0ef41Sopenharmony_ci // Test that enabled tracing references do not get garbage collected 1001cb0ef41Sopenharmony_ci // until after they are disabled. 1011cb0ef41Sopenharmony_ci { 1021cb0ef41Sopenharmony_ci { 1031cb0ef41Sopenharmony_ci let tracing3 = createTracing({ categories: [ 'abc' ] }); 1041cb0ef41Sopenharmony_ci tracing3.enable(); 1051cb0ef41Sopenharmony_ci assert.strictEqual(getEnabledCategories(), 'abc'); 1061cb0ef41Sopenharmony_ci tracing3 = undefined; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci global.gc(); 1091cb0ef41Sopenharmony_ci assert.strictEqual(getEnabledCategories(), 'abc'); 1101cb0ef41Sopenharmony_ci // Not able to disable the thing after this point, however. 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci { 1141cb0ef41Sopenharmony_ci common.expectWarning( 1151cb0ef41Sopenharmony_ci 'Warning', 1161cb0ef41Sopenharmony_ci 'Possible trace_events memory leak detected. There are more than ' + 1171cb0ef41Sopenharmony_ci '10 enabled Tracing objects.'); 1181cb0ef41Sopenharmony_ci for (let n = 0; n < 10; n++) { 1191cb0ef41Sopenharmony_ci const tracing = createTracing({ categories: [ `a${n}` ] }); 1201cb0ef41Sopenharmony_ci tracing.enable(); 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci testApiInChildProcess(['--trace-event-categories', 'foo'], () => { 1251cb0ef41Sopenharmony_ci testApiInChildProcess(['--trace-event-categories', 'foo']); 1261cb0ef41Sopenharmony_ci }); 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_cifunction testApiInChildProcess(execArgs, cb) { 1301cb0ef41Sopenharmony_ci tmpdir.refresh(); 1311cb0ef41Sopenharmony_ci // Save the current directory so we can chdir back to it later 1321cb0ef41Sopenharmony_ci const parentDir = process.cwd(); 1331cb0ef41Sopenharmony_ci process.chdir(tmpdir.path); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci const expectedBegins = [{ cat: 'foo', name: 'test1' }]; 1361cb0ef41Sopenharmony_ci const expectedEnds = [{ cat: 'foo', name: 'test1' }]; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci const proc = cp.fork(__filename, 1391cb0ef41Sopenharmony_ci ['child'], 1401cb0ef41Sopenharmony_ci { 1411cb0ef41Sopenharmony_ci execArgv: [ 1421cb0ef41Sopenharmony_ci '--expose-gc', 1431cb0ef41Sopenharmony_ci '--expose-internals', 1441cb0ef41Sopenharmony_ci '--no-warnings', 1451cb0ef41Sopenharmony_ci ...execArgs, 1461cb0ef41Sopenharmony_ci ] 1471cb0ef41Sopenharmony_ci }); 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci proc.once('exit', common.mustCall(() => { 1501cb0ef41Sopenharmony_ci const file = path.join(tmpdir.path, 'node_trace.1.log'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci assert(fs.existsSync(file)); 1531cb0ef41Sopenharmony_ci fs.readFile(file, common.mustSucceed((data) => { 1541cb0ef41Sopenharmony_ci const traces = JSON.parse(data.toString()).traceEvents 1551cb0ef41Sopenharmony_ci .filter((trace) => trace.cat !== '__metadata'); 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci assert.strictEqual( 1581cb0ef41Sopenharmony_ci traces.length, 1591cb0ef41Sopenharmony_ci expectedBegins.length + expectedEnds.length); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci traces.forEach((trace) => { 1621cb0ef41Sopenharmony_ci assert.strictEqual(trace.pid, proc.pid); 1631cb0ef41Sopenharmony_ci switch (trace.ph) { 1641cb0ef41Sopenharmony_ci case 'b': { 1651cb0ef41Sopenharmony_ci const expectedBegin = expectedBegins.shift(); 1661cb0ef41Sopenharmony_ci assert.strictEqual(trace.cat, expectedBegin.cat); 1671cb0ef41Sopenharmony_ci assert.strictEqual(trace.name, expectedBegin.name); 1681cb0ef41Sopenharmony_ci break; 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci case 'e': { 1711cb0ef41Sopenharmony_ci const expectedEnd = expectedEnds.shift(); 1721cb0ef41Sopenharmony_ci assert.strictEqual(trace.cat, expectedEnd.cat); 1731cb0ef41Sopenharmony_ci assert.strictEqual(trace.name, expectedEnd.name); 1741cb0ef41Sopenharmony_ci break; 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci default: 1771cb0ef41Sopenharmony_ci assert.fail('Unexpected trace event phase'); 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci }); 1801cb0ef41Sopenharmony_ci process.chdir(parentDir); 1811cb0ef41Sopenharmony_ci cb && process.nextTick(cb); 1821cb0ef41Sopenharmony_ci })); 1831cb0ef41Sopenharmony_ci })); 1841cb0ef41Sopenharmony_ci} 185