From 33119c2286bd617262210944258c6d6e1cae7202 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Mon, 28 May 2018 14:48:47 -0300 Subject: [PATCH 1/2] test: create new directory v8-updates `v8-updates` holds all tests related to V8 updates, for example, testing for postmortem metadata chages. --- Makefile | 6 +++++- test/parallel/parallel.status | 2 -- .../test-postmortem-metadata.js | 0 test/v8-updates/testcfg.py | 6 ++++++ test/v8-updates/v8-updates.status | 21 +++++++++++++++++++ tools/test.py | 3 ++- 6 files changed, 34 insertions(+), 4 deletions(-) rename test/{parallel => v8-updates}/test-postmortem-metadata.js (100%) create mode 100644 test/v8-updates/testcfg.py create mode 100644 test/v8-updates/v8-updates.status diff --git a/Makefile b/Makefile index a7099947c72a78..0f45cc2fe7c89d 100644 --- a/Makefile +++ b/Makefile @@ -560,6 +560,7 @@ test-with-async-hooks: .PHONY: test-v8-all .PHONY: test-v8-benchmarks .PHONY: test-v8-intl +.PHONY: test-v8-updates ifneq ("","$(wildcard deps/v8/tools/run-tests.py)") # Related CI job: node-test-commit-v8-linux test-v8: v8 ## Runs the V8 test suite on deps/v8. @@ -580,7 +581,10 @@ test-v8-benchmarks: v8 benchmarks \ $(TAP_V8_BENCHMARKS) -test-v8-all: test-v8 test-v8-intl test-v8-benchmarks +test-v8-updates: + $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) v8-updates + +test-v8-all: test-v8 test-v8-intl test-v8-benchmarks test-v8-updates # runs all v8 tests else test-v8 test-v8-intl test-v8-benchmarks test-v8-all: diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index e4b757bbd3dac9..f79a3b149a8edc 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -5,8 +5,6 @@ prefix parallel # sample-test : PASS,FLAKY [true] # This section applies to all platforms -# Postmortem debugging data is prone to accidental removal during V8 updates. -test-postmortem-metadata: PASS,FLAKY [$system==win32] test-child-process-fork-net: PASS,FLAKY diff --git a/test/parallel/test-postmortem-metadata.js b/test/v8-updates/test-postmortem-metadata.js similarity index 100% rename from test/parallel/test-postmortem-metadata.js rename to test/v8-updates/test-postmortem-metadata.js diff --git a/test/v8-updates/testcfg.py b/test/v8-updates/testcfg.py new file mode 100644 index 00000000000000..cec2589f9b4c20 --- /dev/null +++ b/test/v8-updates/testcfg.py @@ -0,0 +1,6 @@ +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy + +def GetConfiguration(context, root): + return testpy.ParallelTestConfiguration(context, root, 'v8-updates') diff --git a/test/v8-updates/v8-updates.status b/test/v8-updates/v8-updates.status new file mode 100644 index 00000000000000..46149f4751ffb5 --- /dev/null +++ b/test/v8-updates/v8-updates.status @@ -0,0 +1,21 @@ +prefix v8-updates + +# To mark a test as flaky, list the test name in the appropriate section +# below, without ".js", followed by ": PASS,FLAKY". Example: +# sample-test : PASS,FLAKY + +[true] # This section applies to all platforms + +[$system==win32] + +[$system==linux] + +[$system==macos] + +[$arch==arm || $arch==arm64] + +[$system==solaris] # Also applies to SmartOS + +[$system==freebsd] + +[$system==aix] diff --git a/tools/test.py b/tools/test.py index e5581e8da41c44..48256e956b4f3e 100755 --- a/tools/test.py +++ b/tools/test.py @@ -1553,7 +1553,8 @@ def PrintCrashed(code): 'pummel', 'test-known-issues', 'tick-processor', - 'timers' + 'timers', + 'v8-updates' ] From 4c486e2057833be112dc6a9d2c2c5ed2933946f4 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Wed, 16 May 2018 10:56:13 -0300 Subject: [PATCH 2/2] test: add test for Linux perf This commit adds a test to validate if Linux perf is working correctly on Node.js. The test is marked as flaky because its intention is to let us know when changes on V8 potentially broke Linux perf, so we can fix it before a new version of V8 lands on Node.js master. --- test/fixtures/linux-perf.js | 26 ++++++++++ test/v8-updates/test-linux-perf.js | 81 ++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 test/fixtures/linux-perf.js create mode 100644 test/v8-updates/test-linux-perf.js diff --git a/test/fixtures/linux-perf.js b/test/fixtures/linux-perf.js new file mode 100644 index 00000000000000..011ef19777bd37 --- /dev/null +++ b/test/fixtures/linux-perf.js @@ -0,0 +1,26 @@ +'use strict'; + +const crypto = require('crypto'); + +// Functions should be complex enough for V8 to run them a few times before +// compiling, but not complex enough to always stay in interpreted mode. They +// should also take some time to run, otherwise Linux perf might miss them +// entirely even when sampling at a high frequency. +function functionOne(i) { + for (let j=i; j > 0; j--) { + crypto.createHash('md5').update(functionTwo(i, j)).digest("hex"); + } +} + +function functionTwo(x, y) { + let data = ((((x * y) + (x / y)) * y) ** (x + 1)).toString(); + if (x % 2 == 0) { + return crypto.createHash('md5').update(data.repeat((x % 100) + 1)).digest("hex"); + } else { + return crypto.createHash('md5').update(data.repeat((y % 100) + 1)).digest("hex"); + } +} + +for (let i = 0; i < 1000; i++) { + functionOne(i); +} diff --git a/test/v8-updates/test-linux-perf.js b/test/v8-updates/test-linux-perf.js new file mode 100644 index 00000000000000..0a7f199e040d58 --- /dev/null +++ b/test/v8-updates/test-linux-perf.js @@ -0,0 +1,81 @@ +'use strict'; + +// This test verifies that JavaScript functions are being correctly sampled by +// Linux perf. The test runs a JavaScript script, sampling the execution with +// Linux perf. It then uses `perf script` to generate a human-readable output, +// and uses regular expressions to find samples of the functions defined in +// `fixtures/linux-perf.js`. + +// NOTE (mmarchini): this test is meant to run only on Linux machines with Linux +// perf installed. It will skip if those criteria are not met. + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +if (process.config.variables.node_shared) + common.skip("can't test Linux perf with shared libraries yet"); + +const perfArgs = [ + 'record', + '-F500', + '-g', + '--', + process.execPath, + '--perf-basic-prof', + '--interpreted-frames-native-stack', + '--no-turbo-inlining', // Otherwise simple functions might get inlined. + fixtures.path('linux-perf.js'), +]; + +const perfScriptArgs = [ + 'script', +]; + +const options = { + cwd: tmpdir.path, + encoding: 'utf-8', +}; + +if (!common.isLinux) + common.skip('only testing Linux for now'); + +const perf = spawnSync('perf', perfArgs, options); + +if (perf.error && perf.error.errno === 'ENOENT') + common.skip('perf not found on system'); + +if (perf.status !== 0) { + common.skip(`Failed to execute perf: ${perf.stderr}`); +} + +const perfScript = spawnSync('perf', perfScriptArgs, options); + +if (perf.error) + common.skip(`perf script aborted: ${perf.error.errno}`); + +if (perfScript.status !== 0) { + common.skip(`Failed to execute perf script: ${perfScript.stderr}`); +} + +const interpretedFunctionOneRe = /InterpretedFunction:functionOne/; +const compiledFunctionOneRe = /LazyCompile:\*functionOne/; +const interpretedFunctionTwoRe = /InterpretedFunction:functionTwo/; +const compiledFunctionTwoRe = /LazyCompile:\*functionTwo/; + +const output = perfScript.stdout; + +assert.ok(output.match(interpretedFunctionOneRe), + "Couldn't find interpreted functionOne()"); +assert.ok(output.match(compiledFunctionOneRe), + "Couldn't find compiled functionOne()"); +assert.ok(output.match(interpretedFunctionTwoRe), + "Couldn't find interpreted functionTwo()"); +assert.ok(output.match(compiledFunctionTwoRe), + "Couldn't find compiled functionTwo");