From 1f1ccefb60b24530141719f081c276b2faa81a07 Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Wed, 5 Apr 2023 13:42:42 +0200 Subject: [PATCH 1/2] TS-33126 Fix exclude pattern not applying --- .../CHANGELOG.md | 1 + .../src/instrumenter/Instrumenter.ts | 34 ++-- .../src/instrumenter/Task.ts | 16 +- .../test/unit/Task.test.ts | 167 ++++++++++-------- 4 files changed, 123 insertions(+), 95 deletions(-) diff --git a/packages/teamscale-javascript-instrumenter/CHANGELOG.md b/packages/teamscale-javascript-instrumenter/CHANGELOG.md index 239e9255..e579f12b 100644 --- a/packages/teamscale-javascript-instrumenter/CHANGELOG.md +++ b/packages/teamscale-javascript-instrumenter/CHANGELOG.md @@ -3,6 +3,7 @@ We use [Semantic Versioning](https://semver.org/). # New Release - [fix] The instrumented app did send some garbage information not adding value. +- [fix] `--exclude-bundle` failed to exclude file paths staring with `./` # 0.0.1-beta.51 diff --git a/packages/teamscale-javascript-instrumenter/src/instrumenter/Instrumenter.ts b/packages/teamscale-javascript-instrumenter/src/instrumenter/Instrumenter.ts index 6e3b0a2c..278697ff 100644 --- a/packages/teamscale-javascript-instrumenter/src/instrumenter/Instrumenter.ts +++ b/packages/teamscale-javascript-instrumenter/src/instrumenter/Instrumenter.ts @@ -1,5 +1,6 @@ import { - CollectorSpecifier, FileExcludePattern, + CollectorSpecifier, + FileExcludePattern, InstrumentationTask, OriginSourcePattern, SourceMapFileReference, @@ -88,6 +89,7 @@ export class IstanbulInstrumenter implements IInstrumenter { * * @param collector - The collector to send the coverage information to. * @param taskElement - The task element to perform the instrumentation for. + * @param excludeBundles - A exclude pattern to restrict which bundles should be instrumented * @param sourcePattern - A pattern to restrict the instrumentation to only a fraction of the task element. * @param dumpOriginsFile - A file path where all origins from the source map should be dumped in json format, or undefined if no origins should be dumped */ @@ -98,29 +100,32 @@ export class IstanbulInstrumenter implements IInstrumenter { sourcePattern: OriginSourcePattern, dumpOriginsFile: string | undefined ): Promise { - const inputFileSource = fs.readFileSync(taskElement.fromFile, 'utf8'); - - // We skip files that we have already instrumented - if (inputFileSource.startsWith(IS_INSTRUMENTED_TOKEN)) { - if (!taskElement.isInPlace()) { - writeToFile(taskElement.toFile, inputFileSource); - } - return new TaskResult(0, 0, 0, 1, 0, 0, 0); - } - // Not all file types are supported by the instrumenter if (!this.isFileTypeSupported(taskElement.fromFile)) { + if (!taskElement.isInPlace()) { + copyToFile(taskElement.toFile, taskElement.fromFile); + } return new TaskResult(0, 0, 0, 0, 1, 0, 0); } // We might want to skip the instrumentation of the file if (excludeBundles.isExcluded(taskElement.fromFile)) { if (!taskElement.isInPlace()) { - writeToFile(taskElement.toFile, inputFileSource); + copyToFile(taskElement.toFile, taskElement.fromFile); } return new TaskResult(0, 1, 0, 0, 0, 0, 0); } + const inputFileSource = fs.readFileSync(taskElement.fromFile, 'utf8'); + + // We skip files that we have already instrumented + if (inputFileSource.startsWith(IS_INSTRUMENTED_TOKEN)) { + if (!taskElement.isInPlace()) { + writeToFile(taskElement.toFile, inputFileSource); + } + return new TaskResult(0, 0, 0, 1, 0, 0, 0); + } + // Report progress this.logger.info(`Instrumenting "${path.basename(taskElement.fromFile)}"`); @@ -418,3 +423,8 @@ function writeToFile(filePath: string, fileContent: string) { mkdirp.sync(path.dirname(filePath)); fs.writeFileSync(filePath, fileContent); } + +function copyToFile(targetFilePath: string, sourceFilePath: string) { + mkdirp.sync(path.dirname(targetFilePath)); + fs.copyFileSync(sourceFilePath, targetFilePath); +} diff --git a/packages/teamscale-javascript-instrumenter/src/instrumenter/Task.ts b/packages/teamscale-javascript-instrumenter/src/instrumenter/Task.ts index d2f42db7..54ae0e70 100644 --- a/packages/teamscale-javascript-instrumenter/src/instrumenter/Task.ts +++ b/packages/teamscale-javascript-instrumenter/src/instrumenter/Task.ts @@ -1,6 +1,6 @@ import { Optional } from 'typescript-optional'; import { Contract } from '@cqse/commons'; -import matching from 'micromatch'; +import micromatch from 'micromatch'; import path from 'path'; /** @@ -100,27 +100,24 @@ export class OriginSourcePattern { const normalizedOriginFiles = originFiles.map(normalizePath); if (this.exclude) { - const matchedToExclude = matching(normalizedOriginFiles, this.exclude); + const matchedToExclude = micromatch(normalizedOriginFiles, this.exclude); if (originFiles.length === matchedToExclude.length) { return false; } } if (this.include) { - const matchedToInclude = matching(normalizedOriginFiles, this.include || ['**']); - return matchedToInclude.length > 0; + return micromatch.some(normalizedOriginFiles, this.include || ['**']); } return true; } - } /** * Pattern describing files (bundles) to not instrument. */ export class FileExcludePattern { - /** * Glob pattern describing a set of files to be excluded in the instrumentation process. */ @@ -134,7 +131,7 @@ export class FileExcludePattern { * Return `true` if the given `filePath` is matched by any of the patterns in `exclude`. */ public isExcluded(filePath: string): boolean { - return matching([filePath], this.exclude).length === 1; + return micromatch.isMatch(normalizePath(filePath), this.exclude); } } @@ -169,10 +166,7 @@ function normalizePath(toNormalize: string): string { } function removeTrailingCurrentWorkingDir(removeFrom: string): string { - return removePrefix( - 'webpack:///', - removePrefix('.' + path.sep, removeFrom) - ); + return removePrefix('webpack:///', removePrefix('.' + path.sep, removeFrom)); } function removePrefix(prefix: string, removeFrom: string): string { diff --git a/packages/teamscale-javascript-instrumenter/test/unit/Task.test.ts b/packages/teamscale-javascript-instrumenter/test/unit/Task.test.ts index 2ab6ce7c..410c4342 100644 --- a/packages/teamscale-javascript-instrumenter/test/unit/Task.test.ts +++ b/packages/teamscale-javascript-instrumenter/test/unit/Task.test.ts @@ -1,82 +1,105 @@ -import { OriginSourcePattern } from '../../src/instrumenter/Task'; +import { FileExcludePattern, OriginSourcePattern } from '../../src/instrumenter/Task'; -test('Include pattern without extension', () => { - const pattern = new OriginSourcePattern(['./src/app/**/*'], undefined); - const result = pattern.isAnyIncluded(['./src/app/app.components.ts', './src/app/messages/messages.component.ts']); - expect(result).toBeTruthy(); -}); +describe('OriginSourcePattern', () => { + test('Include pattern without extension', () => { + const pattern = new OriginSourcePattern(['./src/app/**/*'], undefined); + const result = pattern.isAnyIncluded([ + './src/app/app.components.ts', + './src/app/messages/messages.component.ts' + ]); + expect(result).toBeTruthy(); + }); -test('Include pattern with extension', () => { - const pattern = new OriginSourcePattern(['src/app/**/*.ts'], undefined); - const result = pattern.isAnyIncluded(['src/app/app.components.ts', 'src/app/messages/messages.component.ts']); - expect(result).toBeTruthy(); -}); + test('Include pattern with extension', () => { + const pattern = new OriginSourcePattern(['src/app/**/*.ts'], undefined); + const result = pattern.isAnyIncluded(['src/app/app.components.ts', 'src/app/messages/messages.component.ts']); + expect(result).toBeTruthy(); + }); -test('Include pattern with extension. Path normalization', () => { - const pattern = new OriginSourcePattern(['src/app/**/*.ts'], undefined); - const result = pattern.isAnyIncluded(['./src/app/app.components.ts', './src/app/messages/messages.component.ts']); - expect(result).toBeTruthy(); -}); + test('Include pattern with extension. Path normalization', () => { + const pattern = new OriginSourcePattern(['src/app/**/*.ts'], undefined); + const result = pattern.isAnyIncluded([ + './src/app/app.components.ts', + './src/app/messages/messages.component.ts' + ]); + expect(result).toBeTruthy(); + }); -test('Exclude pattern with extension. Path normalization', () => { - const pattern = new OriginSourcePattern(undefined, ['src/app/**/*.ts']); - expect( - pattern.isAnyIncluded(['./berg/app/app.components.ts', './src/app/messages/messages.component.ts']) - ).toBeTruthy(); - expect(pattern.isAnyIncluded(['./berg/app/app.components.ts'])).toBeTruthy(); - expect(pattern.isAnyIncluded(['./src/app/app.components.ts'])).toBeFalsy(); -}); + test('Exclude pattern with extension. Path normalization', () => { + const pattern = new OriginSourcePattern(undefined, ['src/app/**/*.ts']); + expect( + pattern.isAnyIncluded(['./berg/app/app.components.ts', './src/app/messages/messages.component.ts']) + ).toBeTruthy(); + expect(pattern.isAnyIncluded(['./berg/app/app.components.ts'])).toBeTruthy(); + expect(pattern.isAnyIncluded(['./src/app/app.components.ts'])).toBeFalsy(); + }); -test('Exclude and include pattern', () => { - const pattern = new OriginSourcePattern(['src/bar/**/*.ts'], ['src/foo/**/*.ts']); - expect( - pattern.isAnyIncluded(['./src/bar/app.components.ts', './src/foo/messages/messages.component.ts']) - ).toBeTruthy(); - expect(pattern.isAnyIncluded(['./src/foo/messages/messages.component.ts'])).toBeFalsy(); - expect(pattern.isAnyIncluded(['./src/bar/messages/messages.component.ts'])).toBeTruthy(); - expect( - pattern.isAnyIncluded([ - './test/foo/unittest.test.ts', - './test/bar/unittest.test.ts', - './build/main.ts', - 'main.ts' - ]) - ).toBeFalsy(); -}); + test('Exclude and include pattern', () => { + const pattern = new OriginSourcePattern(['src/bar/**/*.ts'], ['src/foo/**/*.ts']); + expect( + pattern.isAnyIncluded(['./src/bar/app.components.ts', './src/foo/messages/messages.component.ts']) + ).toBeTruthy(); + expect(pattern.isAnyIncluded(['./src/foo/messages/messages.component.ts'])).toBeFalsy(); + expect(pattern.isAnyIncluded(['./src/bar/messages/messages.component.ts'])).toBeTruthy(); + expect( + pattern.isAnyIncluded([ + './test/foo/unittest.test.ts', + './test/bar/unittest.test.ts', + './build/main.ts', + 'main.ts' + ]) + ).toBeFalsy(); + }); -test('Exclude patterns only', () => { - const pattern = new OriginSourcePattern([], ['src/foo/messages/*.ts']); - expect( - pattern.isAnyIncluded(['./src/bar/app.components.ts', './src/foo/messages/messages.component.ts']) - ).toBeTruthy(); - expect(pattern.isAnyIncluded(['./src/foo/messages/messages.component.ts'])).toBeFalsy(); - expect(pattern.isAnyIncluded(['src/foo/messages/messages.component.ts'])).toBeFalsy(); - expect(pattern.isAnyIncluded(['webpack:///src/foo/messages/messages.component.ts'])).toBeFalsy(); - expect(pattern.isAnyIncluded(['./src/bar/messages/messages.component.ts'])).toBeTruthy(); - expect(pattern.isAnyIncluded(['./test/bar/unittest.test.ts', './build/main.ts', 'main.ts'])).toBeTruthy(); -}); + test('Exclude patterns only', () => { + const pattern = new OriginSourcePattern([], ['src/foo/messages/*.ts']); + expect( + pattern.isAnyIncluded(['./src/bar/app.components.ts', './src/foo/messages/messages.component.ts']) + ).toBeTruthy(); + expect(pattern.isAnyIncluded(['./src/foo/messages/messages.component.ts'])).toBeFalsy(); + expect(pattern.isAnyIncluded(['src/foo/messages/messages.component.ts'])).toBeFalsy(); + expect(pattern.isAnyIncluded(['webpack:///src/foo/messages/messages.component.ts'])).toBeFalsy(); + expect(pattern.isAnyIncluded(['./src/bar/messages/messages.component.ts'])).toBeTruthy(); + expect(pattern.isAnyIncluded(['./test/bar/unittest.test.ts', './build/main.ts', 'main.ts'])).toBeTruthy(); + }); + + test('Exclude and include pattern on file extensions', () => { + const pattern = new OriginSourcePattern( + ['**/*.java', '**/*.md'], + ['**/*.cc', '**/*.cpp', '**/*.h', '**/*.hpp'] + ); + expect(pattern.isAnyIncluded(['./ServerConnector.java', './Server.h'])).toBeTruthy(); + expect( + pattern.isAnyIncluded(['./ServerConnector.java', './ServerVerifier.java', './ServerStarter.java']) + ).toBeTruthy(); + expect( + pattern.isAnyIncluded([ + './ServerConnector.java', + './ServerVerifier.java', + './ServerStarter.java', + 'main.cpp', + 'Logger.java' + ]) + ).toBeTruthy(); + expect(pattern.isAnyIncluded(['proj/docs/README.md'])).toBeTruthy(); + expect(pattern.isAnyIncluded(['proj/src/reader.cpp', 'proj/test/reader_test.cpp'])).toBeFalsy(); + }); -test('Exclude and include pattern on file extensions', () => { - const pattern = new OriginSourcePattern(['**/*.java', '**/*.md'], ['**/*.cc', '**/*.cpp', '**/*.h', '**/*.hpp']); - expect(pattern.isAnyIncluded(['./ServerConnector.java', './Server.h'])).toBeTruthy(); - expect( - pattern.isAnyIncluded(['./ServerConnector.java', './ServerVerifier.java', './ServerStarter.java']) - ).toBeTruthy(); - expect( - pattern.isAnyIncluded([ - './ServerConnector.java', - './ServerVerifier.java', - './ServerStarter.java', - 'main.cpp', - 'Logger.java' - ]) - ).toBeTruthy(); - expect(pattern.isAnyIncluded(['proj/docs/README.md'])).toBeTruthy(); - expect(pattern.isAnyIncluded(['proj/src/reader.cpp', 'proj/test/reader_test.cpp'])).toBeFalsy(); + test('Exclude and include pattern precedence', () => { + const pattern = new OriginSourcePattern( + ['**/ab/**', '**/cd/**'], + ['**/ef/**', '**/gh/**', '**/ij/**', '**/kl/**'] + ); + expect(pattern.isAnyIncluded(['./xy/ef/file1.ts', './kl/file2.ts'])).toBeFalsy(); + expect(pattern.isAnyIncluded(['./xy/ef/file1.ts', './kl/file2.ts', './xy/ij/ab/file3.ts'])).toBeFalsy(); // exclude has precedence over include + }); }); -test('Exclude and include pattern precedence', () => { - const pattern = new OriginSourcePattern(['**/ab/**', '**/cd/**'], ['**/ef/**', '**/gh/**', '**/ij/**', '**/kl/**']); - expect(pattern.isAnyIncluded(['./xy/ef/file1.ts', './kl/file2.ts'])).toBeFalsy(); - expect(pattern.isAnyIncluded(['./xy/ef/file1.ts', './kl/file2.ts', './xy/ij/ab/file3.ts'])).toBeFalsy(); // exclude has precedence over include +describe('FileExcludePattern', () => { + test('Exclude pattern with extension. Path normalization', () => { + const pattern = new FileExcludePattern(['./**/(runtime|vendor)*.js']); + expect(pattern.isExcluded('./src/app/index.js')).toBeFalsy(); + expect(pattern.isExcluded('vendor.5d3bc21.js')).toBeTruthy(); + expect(pattern.isExcluded('./assets/vendor.5d3bc21.js')).toBeTruthy(); + }); }); From a8ab48de65d82e16b5aa1a229406ec7a8bff5d77 Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Wed, 5 Apr 2023 14:39:10 +0200 Subject: [PATCH 2/2] TS-33126 Accept performance regression because we now copy all files --- test/systemtest.mjs | 116 +++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 39 deletions(-) diff --git a/test/systemtest.mjs b/test/systemtest.mjs index 9d6b1044..3afbb3bf 100644 --- a/test/systemtest.mjs +++ b/test/systemtest.mjs @@ -1,4 +1,4 @@ -import net from "net"; +import net from 'net'; import tempfile from 'tempfile'; import { execSync, spawn } from 'child_process'; import path from 'path'; @@ -94,7 +94,7 @@ const caseStudies = [ }, excludeOrigins: [`'src/app/heroes/*.*'`, `'node_modules/**/*.*'`, `'webpack/**/*'`], includeOrigins: [], - maxNormTimeFraction: 8.0 + maxNormTimeFraction: 9.0 } ]; @@ -102,13 +102,13 @@ const caseStudies = [ * Identify the next available port. */ async function identifyNextAvailablePort() { - return new Promise( res => { + return new Promise(res => { const srv = net.createServer(); srv.listen(0, () => { const port = srv.address().port; - srv.close(_ => res(port)) + srv.close(_ => res(port)); }); - }) + }); } /** @@ -214,7 +214,18 @@ function identifyExpectedButAbsent(actual, expected) { function startCollector(coverageFolder, logTargetFile, projectId, collectorPort) { const collector = spawn( 'node', - [`${COLLECTOR_DIR}/dist/src/main.js`, `--port`, collectorPort, `-f`, `${coverageFolder}`, `-l`, `${logTargetFile}`, `-k`, `-e`, `info`], + [ + `${COLLECTOR_DIR}/dist/src/main.js`, + `--port`, + collectorPort, + `-f`, + `${coverageFolder}`, + `-l`, + `${logTargetFile}`, + `-k`, + `-e`, + `info` + ], { env: { ...process.env, @@ -225,11 +236,10 @@ function startCollector(coverageFolder, logTargetFile, projectId, collectorPort) }, TEAMSCALE_PARTITION: 'mockPartition', TEAMSCALE_BRANCH: 'mockBranch', - detached: false + detached: false } ); - collector.stdout.on('data', function (data) { console.log('collector stdout: ' + data.toString()); }); @@ -247,13 +257,20 @@ function startCollector(coverageFolder, logTargetFile, projectId, collectorPort) * Start the Web server process. * @returns {ChildProcessWithoutNullStreams} */ - function startWebServer(distributionFolder) { +function startWebServer(distributionFolder) { const webserver = spawn( 'node', - ['node_modules/.bin/ws', '--static.maxage', '0', - '--hostname', 'localhost', - '--port', SERVER_PORT, - '--directory', distributionFolder], + [ + 'node_modules/.bin/ws', + '--static.maxage', + '0', + '--hostname', + 'localhost', + '--port', + SERVER_PORT, + '--directory', + distributionFolder + ], { detached: false, killSignal: 'SIGKILL', @@ -271,7 +288,7 @@ function startCollector(coverageFolder, logTargetFile, projectId, collectorPort) console.error('webserver stderr: ' + data.toString()); }); - webserver.on('close', (code) => { + webserver.on('close', code => { console.log(`webserver process exited with code ${code}`); }); @@ -343,7 +360,7 @@ function summarizePerformanceMeasures(perfMeasuresByStudy) { return valueInCaseOfZero; } return toCheck; - } + }; const result = {}; result[perfType + 'Base'] = basePerfValue; @@ -355,7 +372,9 @@ function summarizePerformanceMeasures(perfMeasuresByStudy) { result[perfType + 'NoInstNormalized'] = noInstPerfDiffToBase; result[perfType + 'NormalizedDelta'] = withInstPerfDiffToBase - noInstPerfDiffToBase; result[perfType + 'NormalizedFraction'] = withInstPerfDiffToBase / noInstPerfDiffToBase; - result[perfType + 'NormalizedFraction' + String(fractionFactor)] = Math.round(withInstPerfDiffToBase / fractionFactor) / ifZeroElse(1, Math.round(noInstPerfDiffToBase / fractionFactor)); + result[perfType + 'NormalizedFraction' + String(fractionFactor)] = + Math.round(withInstPerfDiffToBase / fractionFactor) / + ifZeroElse(1, Math.round(noInstPerfDiffToBase / fractionFactor)); result[perfType + 'NormalizedFraction'] = withInstPerfDiffToBase / noInstPerfDiffToBase / fractionFactor; return result; }; @@ -380,25 +399,28 @@ function summarizePerformanceMeasures(perfMeasuresByStudy) { } results.push({ - 'study': study.name, - ...computePerfStats(study, 'memory', 'memory_mb_peak', 100, (value) => Math.ceil(value)), - ...computePerfStats(study, 'time', 'duration_secs', 1, (value) => Number(value.toPrecision(2))) + study: study.name, + ...computePerfStats(study, 'memory', 'memory_mb_peak', 100, value => Math.ceil(value)), + ...computePerfStats(study, 'time', 'duration_secs', 1, value => Number(value.toPrecision(2))) }); } return results; - } + }; - const checkPerformanceMeasures = (runtimeResults) => { - for (let i=0; i { + for (let i = 0; i < runtimeResults.length; i++) { const runtimeResult = runtimeResults[i]; // The baseline study is skipped, that is, a +1 is needed: - const study = caseStudies[i+1]; + const study = caseStudies[i + 1]; // We only trigger a violation if the time needed for the study itself is larger than 2s if ('maxNormTimeFraction' in study && runtimeResult.timeWithInstNormalized > 2) { const maxValue = study.maxNormTimeFraction; if (runtimeResult.timeNormalizedFraction > maxValue) { - console.error(`Time overhead added by the instrumentation was too high! ${runtimeResult.timeNormalizedFraction} > ${maxValue}`, study.name); + console.error( + `Time overhead added by the instrumentation was too high! ${runtimeResult.timeNormalizedFraction} > ${maxValue}`, + study.name + ); process.exit(6); } } @@ -407,12 +429,15 @@ function summarizePerformanceMeasures(perfMeasuresByStudy) { if ('maxNormMemoryFraction100' in study && runtimeResult.memoryNormalizedFraction100 > 2) { const maxValue = study.maxNormMemoryFraction100; if (runtimeResult.memoryNormalizedFraction > maxValue) { - console.error(`Memory overhead added by the instrumentation was too high! ${runtimeResult.memoryNormalizedFraction} > ${maxValue}`, study.name); + console.error( + `Memory overhead added by the instrumentation was too high! ${runtimeResult.memoryNormalizedFraction} > ${maxValue}`, + study.name + ); process.exit(7); } } } - } + }; const runtimeResults = aggregatePerformanceResults(); console.log(runtimeResults); @@ -430,13 +455,18 @@ function averagePerformance(samples) { } function profileTestingInBrowser(studyName) { - const runTestsOnSubjectInBrowser = (studyName) => { + const runTestsOnSubjectInBrowser = studyName => { const browserPerformanceFile = tempfile('.json'); console.log('## Running Cypress tests on the subject'); - const command = `${path.join(PROFILER_ROOT_DIR, 'test', 'scripts', 'profile_testing.sh')} ${studyName} ${SERVER_PORT} ${browserPerformanceFile}`; + const command = `${path.join( + PROFILER_ROOT_DIR, + 'test', + 'scripts', + 'profile_testing.sh' + )} ${studyName} ${SERVER_PORT} ${browserPerformanceFile}`; execSync(command, { cwd: PROFILER_ROOT_DIR, stdio: 'inherit' }); return JSON.parse(fs.readFileSync(browserPerformanceFile)); - } + }; // We do one run that is just for warm-up. Its measures are not considered. runTestsOnSubjectInBrowser(studyName); @@ -459,19 +489,22 @@ function instrumentStudy(study, collectorPort) { /** * Attention: This does wildcard expansion!! * See https://stackoverflow.com/questions/11717281/wildcards-in-child-process-spawn - */ - const excludeArgument = - study.excludeOrigins.length > 0 ? `--exclude-origin ${study.excludeOrigins.join(' ')}` : ''; - const includeArgument = - study.includeOrigins.length > 0 ? `--include-origin ${study.includeOrigins.join(' ')}` : ''; + */ + const excludeArgument = study.excludeOrigins.length > 0 ? `--exclude-origin ${study.excludeOrigins.join(' ')}` : ''; + const includeArgument = study.includeOrigins.length > 0 ? `--include-origin ${study.includeOrigins.join(' ')}` : ''; console.log('Include/exclude arguments: ', includeArgument, excludeArgument); const performanceFile = tempfile('.json'); execSync( - `${path.join(PROFILER_ROOT_DIR, 'test', 'scripts', 'profile_instrumentation.sh')} ${fullStudyDistPath} ${collectorPort} ${performanceFile} ${excludeArgument} ${includeArgument}`, + `${path.join( + PROFILER_ROOT_DIR, + 'test', + 'scripts', + 'profile_instrumentation.sh' + )} ${fullStudyDistPath} ${collectorPort} ${performanceFile} ${excludeArgument} ${includeArgument}`, { cwd: INSTRUMENTER_DIR, stdio: 'inherit' } - ); - return JSON.parse(fs.readFileSync(performanceFile)); + ); + return JSON.parse(fs.readFileSync(performanceFile)); } function storePerfResult(perfMeasuresByStudy, studyName, perfKey, perf) { @@ -541,7 +574,7 @@ async function startTeamscaleMockServer(study) { } function checkTeamscaleServerMockInteractions(mockInstance, study) { - const mockedRequests = mockInstance.requests({method: 'POST'}).length; + const mockedRequests = mockInstance.requests({ method: 'POST' }).length; if (mockedRequests === 0 && Object.keys(study.expectCoveredLines).length > 0) { throw new Error('No coverage information was sent to the Teamscale mock server!'); } else { @@ -581,7 +614,12 @@ await (async function runSystemTest() { // Run the tests in the browser on the instrumented version try { const runtimePerformance = profileTestingInBrowser(study.name); - storePerfResult(perfStore, study.name, KEY_PERF_TESTING_WITH_INSTRUMENTATION, runtimePerformance); + storePerfResult( + perfStore, + study.name, + KEY_PERF_TESTING_WITH_INSTRUMENTATION, + runtimePerformance + ); } finally { console.log('## Stopping the collector'); await sleep(1000);