test(config-audit): add token-hotspots scanner test suite (red)
This commit is contained in:
parent
964aa29d16
commit
712058c387
1 changed files with 144 additions and 0 deletions
144
plugins/config-audit/tests/scanners/token-hotspots.test.mjs
Normal file
144
plugins/config-audit/tests/scanners/token-hotspots.test.mjs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import { describe, it, beforeEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { resetCounter } from '../../scanners/lib/output.mjs';
|
||||
import { scan } from '../../scanners/token-hotspots.mjs';
|
||||
import { discoverConfigFiles } from '../../scanners/lib/file-discovery.mjs';
|
||||
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
const FIXTURES = resolve(__dirname, '../fixtures');
|
||||
|
||||
async function fixtureDiscovery(name) {
|
||||
return discoverConfigFiles(resolve(FIXTURES, name));
|
||||
}
|
||||
|
||||
async function runScanner(fixtureName) {
|
||||
resetCounter();
|
||||
const path = resolve(FIXTURES, fixtureName);
|
||||
const discovery = await fixtureDiscovery(fixtureName);
|
||||
return scan(path, discovery);
|
||||
}
|
||||
|
||||
describe('TOK scanner — healthy-project', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('healthy-project');
|
||||
});
|
||||
|
||||
it('returns status ok', () => {
|
||||
assert.equal(result.status, 'ok');
|
||||
});
|
||||
|
||||
it('reports scanner prefix TOK', () => {
|
||||
assert.equal(result.scanner, 'TOK');
|
||||
});
|
||||
|
||||
it('finding IDs match CA-TOK-NNN pattern', () => {
|
||||
for (const f of result.findings) {
|
||||
assert.match(f.id, /^CA-TOK-\d{3}$/);
|
||||
}
|
||||
});
|
||||
|
||||
it('exposes total_estimated_tokens as a number', () => {
|
||||
assert.equal(typeof result.total_estimated_tokens, 'number');
|
||||
assert.ok(result.total_estimated_tokens >= 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — opus-47/cache-breaking', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('opus-47/cache-breaking');
|
||||
});
|
||||
|
||||
it('flags CA-TOK-001 (cache-breaking volatile top)', () => {
|
||||
const f = result.findings.find(x => x.id === 'CA-TOK-001');
|
||||
assert.ok(f, 'expected a CA-TOK-001 finding for cache-breaking fixture');
|
||||
});
|
||||
|
||||
it('CA-TOK-001 severity is medium or low', () => {
|
||||
const f = result.findings.find(x => x.id === 'CA-TOK-001');
|
||||
assert.ok(['medium', 'low'].includes(f.severity), `unexpected severity ${f.severity}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — opus-47/redundant-tools', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('opus-47/redundant-tools');
|
||||
});
|
||||
|
||||
it('emits at least one CA-TOK-002 finding (redundant tool/permission)', () => {
|
||||
const has002 = result.findings.some(f => /^CA-TOK-002$/.test(f.id) || f.title?.toLowerCase().includes('redundant'));
|
||||
assert.ok(has002, 'expected a CA-TOK-002 finding for redundant-tools fixture');
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — opus-47/deep-imports', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('opus-47/deep-imports');
|
||||
});
|
||||
|
||||
it('emits at least one CA-TOK-003 finding (deep @import chain)', () => {
|
||||
const has003 = result.findings.some(f => /^CA-TOK-003$/.test(f.id) || f.title?.toLowerCase().includes('import'));
|
||||
assert.ok(has003, 'expected a CA-TOK-003 finding for deep-imports fixture');
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — opus-47/sonnet-era', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('opus-47/sonnet-era');
|
||||
});
|
||||
|
||||
it('emits no findings above info severity', () => {
|
||||
const nonInfo = result.findings.filter(f => f.severity !== 'info');
|
||||
assert.equal(nonInfo.length, 0, `expected only info findings, got: ${nonInfo.map(f => f.id + '=' + f.severity).join(', ')}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — marketplace scale ordering', () => {
|
||||
it('total_estimated_tokens strictly increases across small → medium → large', async () => {
|
||||
const small = await runScanner('marketplace-small');
|
||||
const medium = await runScanner('marketplace-medium');
|
||||
const large = await runScanner('marketplace-large');
|
||||
|
||||
assert.ok(small.total_estimated_tokens < medium.total_estimated_tokens,
|
||||
`expected small (${small.total_estimated_tokens}) < medium (${medium.total_estimated_tokens})`);
|
||||
assert.ok(medium.total_estimated_tokens < large.total_estimated_tokens,
|
||||
`expected medium (${medium.total_estimated_tokens}) < large (${large.total_estimated_tokens})`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOK scanner — hotspots contract', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runScanner('marketplace-large');
|
||||
});
|
||||
|
||||
it('every finding has a non-empty recommendation', () => {
|
||||
for (const f of result.findings) {
|
||||
assert.ok(f.recommendation, `finding ${f.id} missing recommendation`);
|
||||
assert.ok(String(f.recommendation).length > 0, `finding ${f.id} has empty recommendation`);
|
||||
}
|
||||
});
|
||||
|
||||
it('exposes a hotspots array of length 3–10', () => {
|
||||
assert.ok(Array.isArray(result.hotspots), 'expected result.hotspots to be an array');
|
||||
assert.ok(result.hotspots.length >= 3, `expected ≥3 hotspots, got ${result.hotspots.length}`);
|
||||
assert.ok(result.hotspots.length <= 10, `expected ≤10 hotspots, got ${result.hotspots.length}`);
|
||||
});
|
||||
|
||||
it('every hotspot exposes source/estimated_tokens/rank/recommendations', () => {
|
||||
for (const h of result.hotspots) {
|
||||
assert.ok(typeof h.source === 'string' && h.source.length > 0, 'hotspot.source missing');
|
||||
assert.equal(typeof h.estimated_tokens, 'number', 'hotspot.estimated_tokens not a number');
|
||||
assert.equal(typeof h.rank, 'number', 'hotspot.rank not a number');
|
||||
assert.ok(Array.isArray(h.recommendations), 'hotspot.recommendations not an array');
|
||||
assert.ok(h.recommendations.length >= 1 && h.recommendations.length <= 3,
|
||||
`hotspot.recommendations length should be 1–3, got ${h.recommendations.length}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue