11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci// This test verifies that JavaScript functions are being correctly sampled by 41cb0ef41Sopenharmony_ci// Linux perf. The test runs a JavaScript script, sampling the execution with 51cb0ef41Sopenharmony_ci// Linux perf. It then uses `perf script` to generate a human-readable output, 61cb0ef41Sopenharmony_ci// and uses regular expressions to find samples of the functions defined in 71cb0ef41Sopenharmony_ci// `fixtures/linux-perf.js`. 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci// NOTE (mmarchini): this test is meant to run only on Linux machines with Linux 101cb0ef41Sopenharmony_ci// perf installed. It will skip if those criteria are not met. 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciconst common = require('../common'); 131cb0ef41Sopenharmony_ciif (!common.hasCrypto) 141cb0ef41Sopenharmony_ci common.skip('missing crypto'); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciconst assert = require('assert'); 171cb0ef41Sopenharmony_ciconst { spawnSync } = require('child_process'); 181cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 191cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir'); 201cb0ef41Sopenharmony_citmpdir.refresh(); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ciif (process.config.variables.node_shared) 231cb0ef41Sopenharmony_ci common.skip("can't test Linux perf with shared libraries yet"); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciif (!common.isLinux) 261cb0ef41Sopenharmony_ci common.skip('only testing Linux for now'); 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciconst frequency = 99; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciconst repeat = 5; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// Expected number of samples we'll capture per repeat 331cb0ef41Sopenharmony_ciconst sampleCount = 10; 341cb0ef41Sopenharmony_ciconst sleepTime = sampleCount * (1.0 / frequency); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ciconst perfFlags = [ 371cb0ef41Sopenharmony_ci 'record', 381cb0ef41Sopenharmony_ci `-F${frequency}`, 391cb0ef41Sopenharmony_ci '-g', 401cb0ef41Sopenharmony_ci]; 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ciconst nodeCommonFlags = [ 431cb0ef41Sopenharmony_ci '--perf-basic-prof', 441cb0ef41Sopenharmony_ci '--interpreted-frames-native-stack', 451cb0ef41Sopenharmony_ci '--no-turbo-inlining', // Otherwise simple functions might get inlined. 461cb0ef41Sopenharmony_ci]; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ciconst perfInterpretedFramesArgs = [ 491cb0ef41Sopenharmony_ci ...perfFlags, 501cb0ef41Sopenharmony_ci '--', 511cb0ef41Sopenharmony_ci process.execPath, 521cb0ef41Sopenharmony_ci ...nodeCommonFlags, 531cb0ef41Sopenharmony_ci '--no-opt', 541cb0ef41Sopenharmony_ci fixtures.path('linux-perf.js'), 551cb0ef41Sopenharmony_ci `${sleepTime}`, 561cb0ef41Sopenharmony_ci `${repeat}`, 571cb0ef41Sopenharmony_ci]; 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciconst perfCompiledFramesArgs = [ 601cb0ef41Sopenharmony_ci ...perfFlags, 611cb0ef41Sopenharmony_ci '--', 621cb0ef41Sopenharmony_ci process.execPath, 631cb0ef41Sopenharmony_ci ...nodeCommonFlags, 641cb0ef41Sopenharmony_ci '--always-opt', 651cb0ef41Sopenharmony_ci fixtures.path('linux-perf.js'), 661cb0ef41Sopenharmony_ci `${sleepTime}`, 671cb0ef41Sopenharmony_ci `${repeat}`, 681cb0ef41Sopenharmony_ci]; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ciconst perfArgsList = [ 711cb0ef41Sopenharmony_ci perfInterpretedFramesArgs, perfCompiledFramesArgs, 721cb0ef41Sopenharmony_ci]; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciconst perfScriptArgs = [ 751cb0ef41Sopenharmony_ci 'script', 761cb0ef41Sopenharmony_ci]; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ciconst options = { 791cb0ef41Sopenharmony_ci cwd: tmpdir.path, 801cb0ef41Sopenharmony_ci encoding: 'utf-8', 811cb0ef41Sopenharmony_ci}; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cilet output = ''; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_cifor (const perfArgs of perfArgsList) { 861cb0ef41Sopenharmony_ci const perf = spawnSync('perf', perfArgs, options); 871cb0ef41Sopenharmony_ci assert.ifError(perf.error); 881cb0ef41Sopenharmony_ci if (perf.status !== 0) 891cb0ef41Sopenharmony_ci throw new Error(`Failed to execute 'perf': ${perf.stderr}`); 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci const perfScript = spawnSync('perf', perfScriptArgs, options); 921cb0ef41Sopenharmony_ci assert.ifError(perfScript.error); 931cb0ef41Sopenharmony_ci if (perfScript.status !== 0) 941cb0ef41Sopenharmony_ci throw new Error(`Failed to execute perf script: ${perfScript.stderr}`); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci output += perfScript.stdout; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ciconst interpretedFunctionOneRe = /~functionOne/; 1001cb0ef41Sopenharmony_ciconst compiledFunctionOneRe = /\*functionOne/; 1011cb0ef41Sopenharmony_ciconst interpretedFunctionTwoRe = /~functionTwo/; 1021cb0ef41Sopenharmony_ciconst compiledFunctionTwoRe = /\*functionTwo/; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_cifunction makeAssertMessage(message) { 1051cb0ef41Sopenharmony_ci return message + '\nPerf output:\n\n' + output; 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ciassert.ok(output.match(interpretedFunctionOneRe), 1091cb0ef41Sopenharmony_ci makeAssertMessage("Couldn't find interpreted functionOne()")); 1101cb0ef41Sopenharmony_ciassert.ok(output.match(compiledFunctionOneRe), 1111cb0ef41Sopenharmony_ci makeAssertMessage("Couldn't find compiled functionOne()")); 1121cb0ef41Sopenharmony_ciassert.ok(output.match(interpretedFunctionTwoRe), 1131cb0ef41Sopenharmony_ci makeAssertMessage("Couldn't find interpreted functionTwo()")); 1141cb0ef41Sopenharmony_ciassert.ok(output.match(compiledFunctionTwoRe), 1151cb0ef41Sopenharmony_ci makeAssertMessage("Couldn't find compiled functionTwo")); 116