Spaces:
Running
Running
File size: 6,132 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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | /**
* Unit tests for OpsetChecker.compute()
* Validates: Requirements 22.1, 22.2, 22.3, 22.4, 22.5
*/
import { describe, it, expect } from 'vitest';
const STANDARD_OPSETS = [7, 9, 11, 13, 15, 17, 18, 19, 20, 21];
/**
* Mirror the pure compute logic from OpsetChecker for testability.
*/
function computeOpsetData(parsedModel) {
const modelOpset = (parsedModel && parsedModel.metadata && parsedModel.metadata.opsetVersion) || 0;
const compatibility = STANDARD_OPSETS.map((version) => ({
version,
compatible: version >= modelOpset,
}));
const opsetImport = (parsedModel && parsedModel.metadata && Array.isArray(parsedModel.metadata.opsetImport))
? parsedModel.metadata.opsetImport
: [];
const domains = opsetImport.map((op) => ({
domain: op.domain || 'ai.onnx (default)',
version: op.version || 0,
}));
const nodes = (parsedModel && parsedModel.graph && parsedModel.graph.nodes) || [];
const customOperators = [];
const seen = new Set();
for (const node of nodes) {
if (node.domain && node.domain !== '' && node.domain !== 'ai.onnx') {
const key = `${node.domain}::${node.opType}`;
if (!seen.has(key)) {
seen.add(key);
customOperators.push({ name: node.opType || 'Unknown', domain: node.domain });
}
}
}
const allStandard = customOperators.length === 0;
return { modelOpset, compatibility, domains, customOperators, allStandard };
}
describe('OpsetChecker.compute', () => {
it('should return the model opset version (Req 22.1)', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: { nodes: [] },
};
const result = computeOpsetData(model);
expect(result.modelOpset).toBe(13);
});
it('should mark standard versions >= model opset as compatible (Req 22.2)', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: { nodes: [] },
};
const result = computeOpsetData(model);
for (const entry of result.compatibility) {
if (entry.version >= 13) {
expect(entry.compatible).toBe(true);
} else {
expect(entry.compatible).toBe(false);
}
}
});
it('should mark all versions compatible when model opset is very low', () => {
const model = {
metadata: { opsetVersion: 1 },
graph: { nodes: [] },
};
const result = computeOpsetData(model);
expect(result.compatibility.every((e) => e.compatible)).toBe(true);
});
it('should mark most versions incompatible when model opset is very high', () => {
const model = {
metadata: { opsetVersion: 21 },
graph: { nodes: [] },
};
const result = computeOpsetData(model);
const compatibleVersions = result.compatibility.filter((e) => e.compatible);
expect(compatibleVersions.length).toBe(1);
expect(compatibleVersions[0].version).toBe(21);
});
it('should display all domains from opset_import (Req 22.3)', () => {
const model = {
metadata: {
opsetVersion: 13,
opsetImport: [
{ domain: '', version: 13 },
{ domain: 'ai.onnx.ml', version: 2 },
],
},
graph: { nodes: [] },
};
const result = computeOpsetData(model);
expect(result.domains).toHaveLength(2);
expect(result.domains[0].domain).toBe('ai.onnx (default)');
expect(result.domains[0].version).toBe(13);
expect(result.domains[1].domain).toBe('ai.onnx.ml');
expect(result.domains[1].version).toBe(2);
});
it('should list custom domain operators (Req 22.4)', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: {
nodes: [
{ opType: 'Conv', domain: '' },
{ opType: 'Relu', domain: '' },
{ opType: 'CustomOp', domain: 'com.mycompany' },
{ opType: 'AnotherOp', domain: 'com.mycompany' },
],
},
};
const result = computeOpsetData(model);
expect(result.allStandard).toBe(false);
expect(result.customOperators).toHaveLength(2);
expect(result.customOperators[0]).toEqual({ name: 'CustomOp', domain: 'com.mycompany' });
expect(result.customOperators[1]).toEqual({ name: 'AnotherOp', domain: 'com.mycompany' });
});
it('should deduplicate custom operators with same domain and opType', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: {
nodes: [
{ opType: 'CustomOp', domain: 'com.mycompany' },
{ opType: 'CustomOp', domain: 'com.mycompany' },
{ opType: 'CustomOp', domain: 'com.mycompany' },
],
},
};
const result = computeOpsetData(model);
expect(result.customOperators).toHaveLength(1);
});
it('should report allStandard=true when all operators are from default domain (Req 22.5)', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: {
nodes: [
{ opType: 'Conv', domain: '' },
{ opType: 'Relu', domain: '' },
{ opType: 'Add', domain: '' },
],
},
};
const result = computeOpsetData(model);
expect(result.allStandard).toBe(true);
expect(result.customOperators).toHaveLength(0);
});
it('should handle null/undefined model gracefully', () => {
const result = computeOpsetData(null);
expect(result.modelOpset).toBe(0);
expect(result.compatibility.length).toBe(STANDARD_OPSETS.length);
expect(result.domains).toHaveLength(0);
expect(result.customOperators).toHaveLength(0);
expect(result.allStandard).toBe(true);
});
it('should handle model with no opsetImport', () => {
const model = {
metadata: { opsetVersion: 11 },
graph: { nodes: [] },
};
const result = computeOpsetData(model);
expect(result.domains).toHaveLength(0);
});
it('should treat ai.onnx domain nodes as standard', () => {
const model = {
metadata: { opsetVersion: 13 },
graph: {
nodes: [
{ opType: 'Conv', domain: 'ai.onnx' },
{ opType: 'Relu', domain: '' },
],
},
};
const result = computeOpsetData(model);
expect(result.allStandard).toBe(true);
});
});
|