proposal-approve-rbac-fix-performance.test.mjs
79 lines 3.4 KB
Raw
sha256:0d530f9ef27b8b75547d1db7701a74bc77b77aa8f3d7fa3a8672cf2af36e63bb reconcile: import GitHub-direct RBAC/OAuth/companion and ho… Human minor ⚠ breaking 18 hours ago
1 /**
2 * Performance tests — proposal approve RBAC fix.
3 *
4 * Verifies the fix does not introduce measurable latency regressions in:
5 * - jwt.verify on the bridge fallback path (should be negligible vs. a real network call).
6 * - Set.has lookup for admin override (O(1) data structure).
7 * - The added bridgeResolved flag (zero-cost boolean).
8 *
9 * Thresholds are conservative (×10 buffer) to be stable across CI machines.
10 */
11
12 import { test, describe } from 'node:test';
13 import assert from 'node:assert/strict';
14 import jwt from 'jsonwebtoken';
15
16 const SECRET = 'perf-test-secret-for-jwt';
17
18 describe('Performance: jwt.verify on fallback path', () => {
19 const token = jwt.sign({ sub: 'google:perf-user', role: 'admin' }, SECRET, { expiresIn: '1h' });
20
21 test('single jwt.verify completes in < 5ms', () => {
22 const start = performance.now();
23 jwt.verify(token, SECRET);
24 const elapsed = performance.now() - start;
25 assert.ok(elapsed < 5, `jwt.verify took ${elapsed.toFixed(2)}ms (must be < 5ms)`);
26 });
27
28 test('100 sequential jwt.verify calls complete in < 100ms', () => {
29 const start = performance.now();
30 for (let i = 0; i < 100; i++) jwt.verify(token, SECRET);
31 const elapsed = performance.now() - start;
32 assert.ok(elapsed < 100, `100 verifications in ${elapsed.toFixed(0)}ms (must be < 100ms)`);
33 });
34
35 test('jwt.verify does not allocate more than expected (no obvious memory leak)', () => {
36 const before = process.memoryUsage().heapUsed;
37 for (let i = 0; i < 1000; i++) jwt.verify(token, SECRET);
38 // Force GC hint (not guaranteed but helps in some environments)
39 if (typeof global.gc === 'function') global.gc();
40 const after = process.memoryUsage().heapUsed;
41 const growthKb = (after - before) / 1024;
42 // Allow up to 2MB growth (conservative for 1000 allocations)
43 assert.ok(growthKb < 2048, `Heap grew by ${growthKb.toFixed(0)}KB for 1000 verifications (must be < 2048KB)`);
44 });
45 });
46
47 describe('Performance: Set.has for admin override', () => {
48 test('Set.has on 10,000-entry set completes in < 1ms per call', () => {
49 const adminSet = new Set(Array.from({ length: 10000 }, (_, i) => `google:admin-${i}`));
50 adminSet.add('google:the-target');
51 const start = performance.now();
52 for (let i = 0; i < 10000; i++) adminSet.has('google:the-target');
53 const elapsed = performance.now() - start;
54 // 10,000 Set.has calls should complete well under 10ms (O(1) amortised)
55 assert.ok(elapsed < 10, `10,000 Set.has calls in ${elapsed.toFixed(2)}ms (must be < 10ms)`);
56 });
57
58 test('Set.has miss (not-admin) is equally fast', () => {
59 const adminSet = new Set(['google:one-admin']);
60 const start = performance.now();
61 for (let i = 0; i < 10000; i++) adminSet.has(`google:member-${i}`);
62 const elapsed = performance.now() - start;
63 assert.ok(elapsed < 10, `10,000 Set.has misses in ${elapsed.toFixed(2)}ms (must be < 10ms)`);
64 });
65 });
66
67 describe('Performance: bridgeResolved flag overhead', () => {
68 test('boolean flag assignment in tight loop is sub-millisecond', () => {
69 const start = performance.now();
70 let bridgeResolved = false;
71 for (let i = 0; i < 1_000_000; i++) {
72 bridgeResolved = false;
73 if (i % 2 === 0) bridgeResolved = true;
74 void bridgeResolved;
75 }
76 const elapsed = performance.now() - start;
77 assert.ok(elapsed < 50, `1M boolean ops in ${elapsed.toFixed(0)}ms (must be < 50ms)`);
78 });
79 });
File History 1 commit
sha256:0d530f9ef27b8b75547d1db7701a74bc77b77aa8f3d7fa3a8672cf2af36e63bb reconcile: import GitHub-direct RBAC/OAuth/companion and ho… Human minor 18 hours ago