Skip to content

Commit

Permalink
fix: use module bfj for json string and perf tuning
Browse files Browse the repository at this point in the history
@W-15724695@
@W-15760648@

Replace json stringify with bfj module
Add tuning properties to streams
Add env vars to adjust buffer size and json format indent
  • Loading branch information
peternhale committed May 22, 2024
1 parent 09e4c72 commit 6319e48
Show file tree
Hide file tree
Showing 14 changed files with 342 additions and 432 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@salesforce/core": "^7.3.9",
"@salesforce/kit": "^3.1.1",
"@types/istanbul-reports": "^3.0.4",
"bfj": "^8.0.0",
"faye": "1.4.0",
"glob": "^10.3.10",
"istanbul-lib-coverage": "^3.2.2",
Expand Down
62 changes: 42 additions & 20 deletions src/reporters/junitFormatTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,41 @@ const timeProperties = [
// properties not in cli junit spec
const skippedProperties = ['skipRate', 'totalLines', 'linesCovered'];

export type JUnitFormatTransformerOptions = ReadableOptions & {
bufferSize?: number;
};

export class JUnitFormatTransformer extends Readable {
private logger: Logger;
private buffer: string;
private bufferSize: number;

constructor(
private readonly testResult: TestResult,
options?: ReadableOptions
options?: JUnitFormatTransformerOptions
) {
super(options);
this.testResult = testResult;
this.logger = Logger.childFromRoot('JUnitFormatTransformer');
this.buffer = '';
this.bufferSize = options?.bufferSize || 256; // Default buffer size is 256
}

private pushToBuffer(chunk: string): void {
this.buffer += chunk;
if (this.buffer.length >= this.bufferSize) {
this.push(this.buffer);
this.buffer = '';
}
}

_read(): void {
this.logger.trace('starting _read');
HeapMonitor.getInstance().checkHeapSize('JUnitFormatTransformer._read');
this.format();
if (this.buffer.length > 0) {
this.push(this.buffer);
}
this.push(null); // Signal the end of the stream
this.logger.trace('finishing _read');
HeapMonitor.getInstance().checkHeapSize('JUnitFormatTransformer._read');
Expand All @@ -51,26 +71,26 @@ export class JUnitFormatTransformer extends Readable {
public format(): void {
const { summary } = this.testResult;

this.push(`<?xml version="1.0" encoding="UTF-8"?>\n`);
this.push(`<testsuites>\n`);
this.push(`${tab}<testsuite name="force.apex" `);
this.push(`timestamp="${summary.testStartTime}" `);
this.push(`hostname="${summary.hostname}" `);
this.push(`tests="${summary.testsRan}" `);
this.push(`failures="${summary.failing}" `);
this.push(`errors="0" `);
this.push(`time="${msToSecond(summary.testExecutionTimeInMs)}">\n`);
this.pushToBuffer(`<?xml version="1.0" encoding="UTF-8"?>\n`);
this.pushToBuffer(`<testsuites>\n`);
this.pushToBuffer(`${tab}<testsuite name="force.apex" `);
this.pushToBuffer(`timestamp="${summary.testStartTime}" `);
this.pushToBuffer(`hostname="${summary.hostname}" `);
this.pushToBuffer(`tests="${summary.testsRan}" `);
this.pushToBuffer(`failures="${summary.failing}" `);
this.pushToBuffer(`errors="0" `);
this.pushToBuffer(`time="${msToSecond(summary.testExecutionTimeInMs)}">\n`);

this.buildProperties();
this.buildTestCases();

this.push(`${tab}</testsuite>\n`);
this.push(`</testsuites>\n`);
this.pushToBuffer(`${tab}</testsuite>\n`);
this.pushToBuffer(`</testsuites>\n`);
}

@elapsedTime()
buildProperties(): void {
this.push(`${tab}${tab}<properties>\n`);
this.pushToBuffer(`${tab}${tab}<properties>\n`);

Object.entries(this.testResult.summary).forEach(([key, value]) => {
if (isEmpty(value) || skippedProperties.includes(key)) {
Expand All @@ -90,12 +110,13 @@ export class JUnitFormatTransformer extends Readable {
value = formatStartTime(value);
}

this.push(
this.pushToBuffer(
`${tab}${tab}${tab}<property name="${key}" value="${value}"/>\n`
);
setImmediate(() => {});
});

this.push(`${tab}${tab}</properties>\n`);
this.pushToBuffer(`${tab}${tab}</properties>\n`);
}

@elapsedTime()
Expand All @@ -104,7 +125,7 @@ export class JUnitFormatTransformer extends Readable {

for (const testCase of testCases) {
const methodName = JUnitFormatTransformer.xmlEscape(testCase.methodName);
this.push(
this.pushToBuffer(
`${tab}${tab}<testcase name="${methodName}" classname="${
testCase.apexClass.fullName
}" time="${msToSecond(testCase.runTime)}">\n`
Expand All @@ -116,14 +137,15 @@ export class JUnitFormatTransformer extends Readable {
) {
let message = isEmpty(testCase.message) ? '' : testCase.message;
message = JUnitFormatTransformer.xmlEscape(message);
this.push(`${tab}${tab}${tab}<failure message="${message}">`);
this.pushToBuffer(`${tab}${tab}${tab}<failure message="${message}">`);
if (testCase.stackTrace) {
this.push(`<![CDATA[${testCase.stackTrace}]]>`);
this.pushToBuffer(`<![CDATA[${testCase.stackTrace}]]>`);
}
this.push(`</failure>\n`);
this.pushToBuffer(`</failure>\n`);
}

this.push(`${tab}${tab}</testcase>\n`);
this.pushToBuffer(`${tab}${tab}</testcase>\n`);
setImmediate(() => {});
}
}

Expand Down
30 changes: 24 additions & 6 deletions src/reporters/tapFormatTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,45 @@ export interface TapResult {
testNumber: number;
}

export type TapFormatTransformerOptions = ReadableOptions & {
bufferSize?: number;
};

export class TapFormatTransformer extends Readable {
private readonly logger: Logger;
private testResult: TestResult;
private epilogue?: string[];
private heapMonitor: HeapMonitor;
private buffer: string;
private bufferSize: number;

constructor(
testResult: TestResult,
epilogue?: string[],
options?: ReadableOptions
options?: TapFormatTransformerOptions
) {
super(options);
this.testResult = testResult;
this.epilogue = epilogue;
this.logger = Logger.childFromRoot('TapFormatTransformer');
this.buffer = '';
this.bufferSize = options?.bufferSize || 256; // Default buffer size is 256
}

private pushToBuffer(chunk: string): void {
this.buffer += chunk;
if (this.buffer.length >= this.bufferSize) {
this.push(this.buffer);
this.buffer = '';
}
}

_read(): void {
this.logger.trace('starting format');
HeapMonitor.getInstance().checkHeapSize('TapFormatTransformer._read');
this.format();
if (this.buffer.length > 0) {
this.push(this.buffer);
}
this.push(null); // Signal the end of the stream
this.logger.trace('finishing format');
HeapMonitor.getInstance().checkHeapSize('TapFormatTransformer._read');
Expand All @@ -50,11 +68,11 @@ export class TapFormatTransformer extends Readable {
public format(): void {
const testPointCount = this.testResult.tests.length;

this.push(`1..${testPointCount}\n`);
this.pushToBuffer(`1..${testPointCount}\n`);
this.buildTapResults();

this.epilogue?.forEach((c) => {
this.push(`# ${c}\n`);
this.pushToBuffer(`# ${c}\n`);
});
}

Expand All @@ -64,9 +82,9 @@ export class TapFormatTransformer extends Readable {
const testNumber = index + 1;
const outcome =
test.outcome === ApexTestResultOutcome.Pass ? 'ok' : 'not ok';
this.push(`${outcome} ${testNumber} ${test.fullName}\n`);
this.pushToBuffer(`${outcome} ${testNumber} ${test.fullName}\n`);
this.buildTapDiagnostics(test).forEach((s) => {
this.push(`# ${s}\n`);
this.pushToBuffer(`# ${s}\n`);
});
});
}
Expand Down
4 changes: 1 addition & 3 deletions src/streaming/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
export { AsyncTestRun, StreamingClient } from './streamingClient';
export { JSONStringifyStream } from './jsonStringifyStream';
export { TestResultStringifyStream } from './testResultStringifyStream';
export {
determineType,
getArrayEntries,
getPrimitiveEntries,
getObjectEntries,
pushArrayToStream
getObjectEntries
} from './utils';
Loading

0 comments on commit 6319e48

Please sign in to comment.