feat: CAP platform requirement + LOAD rejection hint (v3.6.36)
capmem derives the minimum platform from the CAP's Import component
(javacard.framework -> Java Card level via the SDK-kit corpus, int flag)
and /api/cap-info exposes it; the CAP details show it as a Platform row
('Java Card >= 2.2.2 - CAP format 2.1 - int support').
A failed RAM install at a LOAD / INSTALL [for load] step now appends a
hint naming the import requirement and the smaller-block fallback
(ramInstallFailHint, pure): JC VM spec 4.5.2 makes every import a
'>= version' demand on the card's own packages checked while the load
file is verified - live 2026-09-29, a CAP requiring Java Card 2.2.2 was
rejected exactly at the block containing the end of Import (6438 at
240 B blocks, 6985 at 64 B), not at a step count.
sw cache simple-v309; tests: 507 Python / 670 Node.
This commit is contained in:
@@ -119,11 +119,12 @@ test('capMemHtml renders the grouped report: package, requires, memory, componen
|
||||
assert.ok(req.includes('>\u2265 1.0</td>'), req);
|
||||
assert.ok(req.includes('>Oracle JavaCard API</td>'), req);
|
||||
assert.ok(req.includes('>6</td>'), req);
|
||||
// package identity + compiled-against hint derived from the framework version
|
||||
// package identity + platform requirement derived from the framework version
|
||||
assert.ok(out.includes('A0000000620101') && out.includes('>v1.0</td>'), out);
|
||||
assert.ok(out.includes('applet package'), out);
|
||||
assert.ok(out.includes('(javacard.framework)</span>'), out);
|
||||
assert.ok(out.includes('Java Card 2.1.1/2.1.2 \u00b7 CAP format 2.1'), out);
|
||||
assert.ok(out.includes('>Platform</td>'), out);
|
||||
assert.ok(out.includes('Java Card \u2265 2.1.1/2.1.2 \u00b7 CAP format 2.1'), out);
|
||||
// components in load-file order with sizes, shares and the total row
|
||||
assert.ok(out.includes('>Header</td>') && out.includes('>20 B</td>') && out.includes('>1%</td>'), out);
|
||||
assert.ok(out.includes('>Method</td>') && out.includes('>2.7 kB</td>') && out.includes('>93%</td>'), out);
|
||||
@@ -134,6 +135,25 @@ test('capMemHtml renders the grouped report: package, requires, memory, componen
|
||||
assert.strictEqual(capMemHtml(null), '');
|
||||
});
|
||||
|
||||
test('capMemHtml shows the server platform requirement and int support', () => {
|
||||
const mem = memFixture();
|
||||
mem.requires_java_card = '2.2.2';
|
||||
mem.requires_framework = '1.3';
|
||||
mem.needs_int = true;
|
||||
const out = capMemHtml(mem);
|
||||
assert.ok(out.includes('Java Card \u2265 2.2.2 \u00b7 CAP format 2.1 \u00b7 int support'), out);
|
||||
// the server value wins over the local fallback table (fixture import 1.0)
|
||||
assert.ok(!out.includes('2.1.1/2.1.2'), out);
|
||||
});
|
||||
|
||||
test('capMemHtml falls back to the raw framework version outside the corpus', () => {
|
||||
const mem = memFixture();
|
||||
mem.imports = [{ aid: 'A0000000620101', minor: 0, major: 7, refs: 6 }];
|
||||
const out = capMemHtml(mem);
|
||||
assert.ok(out.includes('javacard.framework \u2265 7.0 \u00b7 CAP format 2.1'), out);
|
||||
assert.ok(!out.includes('Java Card'), out);
|
||||
});
|
||||
|
||||
test('capMemHtml skips the import section on a response without imports', () => {
|
||||
const mem = memFixture();
|
||||
delete mem.imports;
|
||||
|
||||
@@ -22,7 +22,7 @@ function extractFunc(src, name) {
|
||||
}
|
||||
|
||||
// Extract chain builder functions and dependencies
|
||||
const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamBuildRowHex', 'ramFmtLifecycle', 'ramFmtPrivileges', 'ramRenderExploreHtml', 'ramStepLine', 'ramGetStatusApdu', 'ramDeleteApdu',
|
||||
const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamBuildRowHex', 'ramFmtLifecycle', 'ramFmtPrivileges', 'ramRenderExploreHtml', 'ramStepLine', 'ramInstallFailHint', 'ramGetStatusApdu', 'ramDeleteApdu',
|
||||
'stkParamsBuild', 'ramRemoteSwOk', 'spPorAccepted', 'ramIncrementCntr', 'ramDeleteFromExplorer', 'ramListingSpi2', 'ramRemoveFromExplorer', 'ramHasInstance', 'ramExpandedQueryApdu',
|
||||
'_parseRawElfEntry', '_parseRawAppEntry', 'ramParseElfStatus', 'ramParseAppStatus', 'parseTLV', '_parseE3Entry',
|
||||
'ramCardIdxAfterRemove', 'ramClearResults', 'ramHideProgress', 'ramOpChanged', 'ramRender', 'ramApplyCard', 'ramExecute', 'decodePrivileges', 'ramActionBtn', 'ramCapToolkitMode', 'ramOpProgressText',
|
||||
@@ -390,6 +390,26 @@ test('ramStepLine shows the PoR verdict and the remote status word', () => {
|
||||
assert.ok(noPor.startsWith('\u2705') && noPor.includes('no PoR'), noPor);
|
||||
});
|
||||
|
||||
test('ramInstallFailHint names the CAP import requirement for a rejected LOAD', () => {
|
||||
globalThis.t = s => s;
|
||||
const failedLoad = {
|
||||
success: false, failed_step: 3,
|
||||
steps: [{ name: 'INSTALL [for load]' }, { name: 'LOAD (1/240)' }, { name: 'LOAD (2/240)', por_sw: '6985' }],
|
||||
};
|
||||
const hint = ramInstallFailHint(failedLoad, { requires_java_card: '2.2.2' });
|
||||
assert.ok(hint.includes('every import version under Requires'), hint);
|
||||
assert.ok(hint.includes('(Java Card \u2265 2.2.2)'), hint);
|
||||
assert.ok(hint.includes('smaller LOAD block'), hint);
|
||||
// without a CAP analysis (INSTALL [for install] ops) the level is omitted
|
||||
const noMem = ramInstallFailHint(failedLoad, null);
|
||||
assert.ok(noMem.includes('every import version under Requires'), noMem);
|
||||
assert.ok(!noMem.includes('Java Card'), noMem);
|
||||
// only a load-related step gets the hint
|
||||
assert.strictEqual(ramInstallFailHint(
|
||||
{ success: false, failed_step: 2, steps: [{ name: 'INSTALL [for load]' }, { name: 'INSTALL [for install]' }] }, null), '');
|
||||
assert.strictEqual(ramInstallFailHint({ success: true, failed_step: 1, steps: [] }, null), '');
|
||||
});
|
||||
|
||||
test('ramOpChanged clears the executed status only on a real op change', () => {
|
||||
const els = fakeRamDocument(['ram-op', 'ram-install-params', 'ram-result', 'ram-explorer', 'ram-steps', 'ram-progress']);
|
||||
_ramOpLast = null;
|
||||
|
||||
Reference in New Issue
Block a user