Skip to content

Commit dc1f530

Browse files
authored
Warn when rcode CRC does not match profiler CRC (#272)
1 parent d097c73 commit dc1f530

5 files changed

Lines changed: 58 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
# [1.2.7](https://github.com/kenherring/ablunit-test-runner/releases/tag/1.2.7) - 2025-05-11 (pre-release)
22

3-
4-
*
3+
* Warn when rcode CRC does not match profiler CRC (#272)
54
* Create codeql.yml (#278)
6-
7-
**Full Changelog**: [1.2.5...1.2.7](https://github.com/kenherring/ablunit-test-runner/compare/1.2.5...1.2.7)
8-
9-
# [1.2.5](https://github.com/kenherring/ablunit-test-runner/releases/tag/1.2.5) - 2025-05-11 (pre-release)
10-
115
* Create dependabot.yml (#275)
126
* Bump the npm_and_yarn group across 1 directory with 2 updates (#277)
137
* Update eslint configuration (#279)
148
* Unit test cleanup and performance (#274)
159
* Increase debug profile wait time to 30s (part 2) (#273)
1610

17-
**Full Changelog**: [1.2.0...1.2.5](https://github.com/kenherring/ablunit-test-runner/compare/1.2.0...1.2.5)
11+
**Full Changelog**: [1.2.0...1.2.7](https://github.com/kenherring/ablunit-test-runner/compare/1.2.0...1.2.7)
1812

1913
# [1.2.0](https://github.com/kenherring/ablunit-test-runner/releases/tag/1.2.0) - 2025-04-26
2014

src/ABLResults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ export class ABLResults implements Disposable {
568568
const uri = Uri.joinPath(Uri.file(profDir), dataFiles[i])
569569
log.debug('parsing profiler data ' + (i+1) + '/' + dataFiles.length + ' from ' + uri.fsPath)
570570

571-
proms.push(new ABLProfile().parseData(uri, this.cfg.ablunitConfig.profiler.writeJson, this.debugLines, this.cfg.ablunitConfig.profiler.ignoreExternalCoverage).then((profJson) => {
571+
proms.push(new ABLProfile().parseData(uri, options, this.cfg.ablunitConfig.profiler.writeJson, this.debugLines, this.cfg.ablunitConfig.profiler.ignoreExternalCoverage).then((profJson) => {
572572
log.debug('parsed profiler data ' + (i+1) + '/' + dataFiles.length + ' ' + profJson.parseDuration)
573573
const item = this.findTest(profJson.description)
574574
if (item) {

src/parse/ProfileParser.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DeclarationCoverage, Position, Range, StatementCoverage, TextDocument, Uri, workspace } from 'vscode'
1+
import { DeclarationCoverage, Position, Range, StatementCoverage, TestRun, TextDocument, Uri, workspace } from 'vscode'
22
import { PropathParser } from 'ABLPropath'
33
import { ABLDebugLines } from 'ABLDebugLines'
44
import { log } from 'ChannelLogger'
@@ -18,7 +18,7 @@ export class ABLProfile {
1818
profJSON?: ABLProfileJson
1919
parseAll = false
2020

21-
async parseData (uri: Uri, writeJson: boolean, debugLines?: ABLDebugLines, ignoreExternalCoverage = true, propath?: PropathParser) {
21+
async parseData (uri: Uri, options: TestRun, writeJson: boolean, debugLines?: ABLDebugLines, ignoreExternalCoverage = true, propath?: PropathParser) {
2222
if (!debugLines) {
2323
// unit testing setup
2424
debugLines = new ABLDebugLines()
@@ -46,7 +46,7 @@ export class ABLProfile {
4646
}
4747

4848
log.debug('section1 ' + sectionLines[1].length)
49-
this.profJSON = new ABLProfileJson(uri, sectionLines[1], debugLines, ignoreExternalCoverage)
49+
this.profJSON = new ABLProfileJson(options, uri, sectionLines[1], debugLines, ignoreExternalCoverage)
5050
log.debug('section2 ' + sectionLines[2].length)
5151
this.profJSON.addModules(sectionLines[2])
5252
if (this.profJSON.modules.length > 0) { // all modules excluded
@@ -308,7 +308,11 @@ export class ABLProfileJson {
308308
ignoredModules: number[] = [0]
309309
private hasSourceMap = false
310310

311-
constructor (public readonly profileUri: Uri, lines: string[], public debugLines: ABLDebugLines, private readonly ignoreExternalCoverage: boolean) {
311+
constructor (private readonly options: TestRun,
312+
public readonly profileUri: Uri,
313+
lines: string[],
314+
public debugLines: ABLDebugLines,
315+
private readonly ignoreExternalCoverage: boolean) {
312316
this.parseDuration = new Duration('parse profile data: ' + profileUri)
313317
this.debugLines = debugLines
314318
if (lines.length > 1) {
@@ -467,6 +471,13 @@ export class ABLProfileJson {
467471
async addSourceMap () {
468472
for (const mod of this.modules) {
469473
const map = await this.debugLines.getSourceMap(mod.SourceUri).then((sourceMap) => {
474+
475+
if (sourceMap?.crc && sourceMap.crc != mod.CrcValue) {
476+
log.warn('crc mismatch for module ' + mod.ModuleName + ' in uri=' + this.profileUri.fsPath + ' (ModuleID=' + mod.ModuleID + ')' +
477+
'\n\t- expected: ' + mod.CrcValue +
478+
'\n\t- got: ' + sourceMap.crc, { testRun: this.options })
479+
}
480+
470481
return sourceMap
471482
}, (e: unknown) => {
472483
log.error('could not get source map for module ' + mod.ModuleName + ' in uri=' + this.profileUri.fsPath + ' (ModuleID=' + mod.ModuleID + ') - ' + e)

src/parse/SourceMapRCodeParser.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,24 @@ export const getSourceMapFromRCode = (propath: PropathParser, uri: Uri) => {
7474
// * Frame (1 per frame)
7575
// * Debugger (1)
7676

77-
const debug = segmentTable.subarray(12, 16)
77+
const size1 = segmentTable.subarray(16, 20)
78+
const size2 = segmentTable.subarray(20, 24)
79+
const size3 = segmentTable.subarray(24, 28)
7880
const debugsize = segmentTable.subarray(28, 32)
79-
const debugLoc = toBase10(debug) + segmentTable.byteOffset + segmentTable.length
81+
const loc1 = toBase10(segmentTable.subarray(0, 4)) + segmentTable.byteOffset + segmentTable.length
82+
const loc2 = toBase10(segmentTable.subarray(4, 8)) + segmentTable.byteOffset + segmentTable.length
83+
const loc3 = toBase10(segmentTable.subarray(8, 12)) + segmentTable.byteOffset + segmentTable.length
84+
const debugLoc = toBase10(segmentTable.subarray(12, 16)) + segmentTable.byteOffset + segmentTable.length
85+
8086
return {
87+
segmentLoc1: loc1,
88+
segmentSize1: toBase10(size1),
89+
segmentLoc2: loc2,
90+
segmentSize2: toBase10(size2),
91+
segmentLoc3: loc3,
92+
segmentSize3: toBase10(size3),
8193
debugLoc: debugLoc,
82-
debugSize: toBase10(debugsize)
94+
debugSize: toBase10(debugsize),
8395
}
8496
}
8597

@@ -412,6 +424,15 @@ export const getSourceMapFromRCode = (propath: PropathParser, uri: Uri) => {
412424
return debugLines
413425
}
414426

427+
const parseSegment1 = (segment1Bytes: Uint8Array) => {
428+
log.debug('parseSegment1 segment1Bytes.length=' + segment1Bytes.length)
429+
const crcLocation = 174
430+
const crc = toBase10(segment1Bytes.subarray(crcLocation, crcLocation + 2))
431+
return {
432+
crc: crc,
433+
}
434+
}
435+
415436
const parseDebugSegment = async (debugBytes: Uint8Array) => {
416437
const debugBytes32 = new Uint32Array(debugBytes.length / 4)
417438
for (let i=0; i < debugBytes.length; i=i+4) {
@@ -453,6 +474,9 @@ export const getSourceMapFromRCode = (propath: PropathParser, uri: Uri) => {
453474
const rawSignatureTable = raw.subarray(headerInfo.signatureTableLoc, headerInfo.signatureTableLoc + headerInfo.signatureTableSize)
454475
const signatures = parseSignatureTable(rawSignatureTable)
455476

477+
const segment1Bytes = raw.subarray(segmentInfo.segmentLoc1, segmentInfo.segmentLoc1 + segmentInfo.segmentSize1)
478+
const segment1Info = parseSegment1(segment1Bytes)
479+
456480
let debugInfo: SourceMapItem[] = []
457481
if (segmentInfo.debugSize > 0) {
458482
const debugBytes = raw.slice(segmentInfo.debugLoc, segmentInfo.debugLoc + segmentInfo.debugSize)
@@ -467,6 +491,7 @@ export const getSourceMapFromRCode = (propath: PropathParser, uri: Uri) => {
467491
includes: includes,
468492
declarations: declarations,
469493
signatures: signatures,
494+
crc: segment1Info.crc,
470495
}
471496

472497
return sourceMap

test/parse/SourceMapRCodeParser.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,18 @@ test('SourceMapRCodeParser.test_4', async () => {
9191
return
9292
})
9393

94+
test('SourceMapRCodeParser.test_5', async () => {
95+
const propath = new PropathParser()
96+
const testuri = toUri('test_4/destructorSimple.cls')
97+
await getSourceMap(propath, testuri).then((sourceMap) => {
98+
log.info('sourceMap.crc=' + sourceMap.crc)
99+
assert.equal(sourceMap.crc, 8413)
100+
return true
101+
}, (e: unknown) => {
102+
assert.fail('Error in test_5: e=' + (e instanceof Error ? e.message : String(e)))
103+
})
104+
})
105+
94106
async function getSourceMap (propath: PropathParser, uri: Uri) {
95107
const sourceMap = await getSourceMapFromRCode(propath, uri)
96108
if (!sourceMap) {

0 commit comments

Comments
 (0)