Spaces:
Running
Running
File size: 4,900 Bytes
9bd422a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | /**
* Unit tests for ModelComplexity.compute() and _formatParameterCount()
* Validates: Requirements 20.1, 20.2, 20.3, 20.4, 20.5
*/
import { describe, it, expect } from 'vitest';
// Mirror the pure compute logic from ModelComplexity
function computeComplexity(parsedModel) {
const nodes = (parsedModel && parsedModel.graph && parsedModel.graph.nodes) || [];
const edges = (parsedModel && parsedModel.graph && parsedModel.graph.edges) || [];
const initializers = (parsedModel && parsedModel.initializers) || [];
let totalParameters = 0;
let memoryFootprint = 0;
for (const init of initializers) {
totalParameters += (init.elementCount || 0);
memoryFootprint += (init.size || 0);
}
return {
totalParameters,
memoryFootprint,
totalNodes: nodes.length,
totalEdges: edges.length,
totalInitializers: initializers.length,
};
}
// Mirror the formatting logic
function formatParameterCount(count) {
if (count == null || isNaN(count) || count === 0) return '0';
const abs = Math.abs(count);
if (abs >= 1e9) return (count / 1e9).toFixed(1).replace(/\.0$/, '') + 'B';
if (abs >= 1e6) return (count / 1e6).toFixed(1).replace(/\.0$/, '') + 'M';
if (abs >= 1e3) return (count / 1e3).toFixed(1).replace(/\.0$/, '') + 'K';
return String(count);
}
describe('ModelComplexity.compute', () => {
it('should sum elementCount from all initializers as totalParameters', () => {
const model = {
graph: { nodes: [{ id: '1', opType: 'Conv' }], edges: [] },
initializers: [
{ name: 'w1', elementCount: 1000, size: 4000 },
{ name: 'w2', elementCount: 500, size: 2000 },
{ name: 'b1', elementCount: 64, size: 256 },
],
};
const m = computeComplexity(model);
expect(m.totalParameters).toBe(1564);
expect(m.memoryFootprint).toBe(6256);
expect(m.totalInitializers).toBe(3);
});
it('should sum size from all initializers as memoryFootprint', () => {
const model = {
graph: { nodes: [], edges: [] },
initializers: [
{ name: 'w1', elementCount: 100, size: 400 },
{ name: 'w2', elementCount: 200, size: 800 },
],
};
const m = computeComplexity(model);
expect(m.memoryFootprint).toBe(1200);
});
it('should count nodes, edges, and initializers', () => {
const model = {
graph: {
nodes: [{ id: '1' }, { id: '2' }, { id: '3' }],
edges: [{ source: '1', target: '2' }, { source: '2', target: '3' }],
},
initializers: [{ name: 'w1', elementCount: 10, size: 40 }],
};
const m = computeComplexity(model);
expect(m.totalNodes).toBe(3);
expect(m.totalEdges).toBe(2);
expect(m.totalInitializers).toBe(1);
});
it('should handle no initializers (0 parameters)', () => {
const model = {
graph: { nodes: [{ id: '1' }], edges: [] },
initializers: [],
};
const m = computeComplexity(model);
expect(m.totalParameters).toBe(0);
expect(m.memoryFootprint).toBe(0);
expect(m.totalInitializers).toBe(0);
});
it('should handle null/undefined model', () => {
const m = computeComplexity(null);
expect(m.totalParameters).toBe(0);
expect(m.memoryFootprint).toBe(0);
expect(m.totalNodes).toBe(0);
expect(m.totalEdges).toBe(0);
expect(m.totalInitializers).toBe(0);
});
it('should handle initializers with missing elementCount or size', () => {
const model = {
graph: { nodes: [], edges: [] },
initializers: [
{ name: 'w1' },
{ name: 'w2', elementCount: 100 },
{ name: 'w3', size: 500 },
],
};
const m = computeComplexity(model);
expect(m.totalParameters).toBe(100);
expect(m.memoryFootprint).toBe(500);
});
});
describe('formatParameterCount', () => {
it('should return "0" for zero', () => {
expect(formatParameterCount(0)).toBe('0');
});
it('should return plain number for counts under 1000', () => {
expect(formatParameterCount(500)).toBe('500');
expect(formatParameterCount(999)).toBe('999');
});
it('should format thousands with K suffix', () => {
expect(formatParameterCount(1500)).toBe('1.5K');
expect(formatParameterCount(10000)).toBe('10K');
expect(formatParameterCount(999999)).toBe('1000K');
});
it('should format millions with M suffix', () => {
expect(formatParameterCount(1000000)).toBe('1M');
expect(formatParameterCount(25600000)).toBe('25.6M');
expect(formatParameterCount(138000000)).toBe('138M');
});
it('should format billions with B suffix', () => {
expect(formatParameterCount(1200000000)).toBe('1.2B');
expect(formatParameterCount(7000000000)).toBe('7B');
});
it('should return "0" for null/undefined/NaN', () => {
expect(formatParameterCount(null)).toBe('0');
expect(formatParameterCount(undefined)).toBe('0');
expect(formatParameterCount(NaN)).toBe('0');
});
});
|