Files
Web_FreeCAD_Bitbybit/scripts/check-freecad-partdesign-transform-oracle.mjs

58 lines
7.7 KiB
JavaScript

import { readFile } from 'node:fs/promises'
import { resolve } from 'node:path'
const root = resolve(new URL('..', import.meta.url).pathname)
const load = async (path) => JSON.parse(await readFile(resolve(root, path), 'utf8'))
const oracle = await load('config/freecad-partdesign-transform-oracle.json')
if (oracle.schemaVersion !== 1 || oracle.baselineId !== 'freecad-1.1.1-partdesign-transform-oracle' || oracle.freecadVersion !== '1.1.1' || oracle.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || oracle.status !== 'pass' || oracle.tolerance !== 1e-7 || oracle.summary?.cases !== 10 || oracle.summary?.passed !== 10 || oracle.summary.successCases !== 6 || oracle.summary.successPassed !== 6 || oracle.summary.failureCases !== 4 || oracle.summary.failurePassed !== 4 || oracle.summary.rejected !== 4 || oracle.summary.acceptedEmpty !== 0) throw new Error('FreeCAD PartDesign transform oracle baseline is invalid.')
const byId = new Map(oracle.cases?.map((entry) => [entry.id, entry]) ?? [])
const linear = byId.get('linear-feature-list')
if (!linear || linear.typeId !== 'PartDesign::LinearPattern' || linear.transformMode !== 'Features' || JSON.stringify(linear.originals) !== JSON.stringify(['Boss']) || linear.direction !== 'X_Axis' || linear.occurrences !== 3 || linear.length !== 12 || linear.solids !== 1 || linear.status !== 'Valid' || Math.abs(linear.volume - 423.99999999999994) > oracle.tolerance) throw new Error('FreeCAD Feature-list LinearPattern evidence is invalid.')
const mirrored = byId.get('mirrored-feature-list')
if (!mirrored || mirrored.typeId !== 'PartDesign::Mirrored' || mirrored.transformMode !== 'Features' || JSON.stringify(mirrored.originals) !== JSON.stringify(['Boss']) || mirrored.plane !== 'YZ_Plane' || mirrored.solids !== 1 || mirrored.status !== 'Valid' || Math.abs(mirrored.volume - 416.00000000000006) > oracle.tolerance) throw new Error('FreeCAD Feature-list Mirrored evidence is invalid.')
const polar = byId.get('polar-feature-list')
if (!polar || polar.typeId !== 'PartDesign::PolarPattern' || polar.transformMode !== 'Features' || JSON.stringify(polar.originals) !== JSON.stringify(['Box']) || polar.axis !== 'X_Axis' || polar.angle !== 360 || polar.occurrences !== 4 || polar.solids !== 1 || polar.status !== 'Valid' || Math.abs(polar.volume - 4000) > oracle.tolerance) throw new Error('FreeCAD Feature-list PolarPattern evidence is invalid.')
const multi = byId.get('multi-transform-feature-list')
if (!multi || multi.typeId !== 'PartDesign::MultiTransform' || multi.transformMode !== 'Features' || JSON.stringify(multi.originals) !== JSON.stringify(['Pad']) || JSON.stringify(multi.transformations) !== JSON.stringify(['PartDesign::Mirrored', 'PartDesign::LinearPattern', 'PartDesign::PolarPattern']) || multi.solids !== 1 || multi.status !== 'Valid' || Math.abs(multi.volume - 20000) > oracle.tolerance) throw new Error('FreeCAD Feature-list MultiTransform evidence is invalid.')
const expectedFailures = new Map([
['PartDesign::Mirrored', { id: 'mirrored-missing-reference', status: 'No mirror plane reference specified', shapeNull: true, staleShapePreserved: false }],
['PartDesign::MultiTransform', { id: 'multitransform-missing-reference', status: 'Shape index 999 out of bound 12', shapeNull: false, staleShapePreserved: true }],
['PartDesign::LinearPattern', { id: 'linearpattern-missing-reference', status: 'Shape index 999 out of bound 12', shapeNull: true, staleShapePreserved: false }],
['PartDesign::PolarPattern', { id: 'polarpattern-missing-reference', status: 'No axis reference specified', shapeNull: true, staleShapePreserved: false }],
])
for (const [typeId, expected] of expectedFailures) {
const fixture = oracle.cases.find((entry) => entry.typeId === typeId && entry.expected === 'rejected')
if (!fixture || fixture.id !== expected.id || fixture.inputClass !== 'valid-original-missing-transform-reference' || fixture.observed !== 'rejected' || fixture.passed !== true || fixture.status !== expected.status || fixture.shapeNull !== expected.shapeNull || fixture.staleShapePreserved !== expected.staleShapePreserved || !fixture.state?.includes('Invalid') || JSON.stringify(fixture.originals) !== JSON.stringify(['Boss'])) throw new Error(`FreeCAD ${typeId} rejected transform evidence is invalid.`)
}
if (JSON.stringify(byId.get('multitransform-missing-reference')?.transformations) !== JSON.stringify(['PartDesign::LinearPattern'])) throw new Error('FreeCAD MultiTransform rejected child evidence is invalid.')
const tap = byId.get('iso-m6-tap-drill')
const modeled = byId.get('iso-m6-modeled-thread')
for (const fixture of [tap, modeled]) {
if (!fixture || fixture.typeId !== 'PartDesign::Hole' || fixture.threaded !== true || fixture.threadType !== 'ISOMetricProfile' || fixture.threadSize !== 'M6x1.0' || fixture.threadDiameter !== 6 || fixture.threadPitch !== 1 || fixture.threadDepthType !== 'Dimension' || fixture.threadDepth !== 6 || fixture.solids !== 1 || fixture.status !== 'Valid' || fixture.properties?.includes('ThreadPitch')) throw new Error(`FreeCAD ISO M6 Hole evidence is invalid: ${fixture?.id ?? 'missing'}.`)
}
if (tap.modeled !== false || tap.threadDirection !== 'Right' || Math.abs(tap.diameter - 5) > oracle.tolerance || Math.abs(tap.volume - 3842.92036732051) > oracle.tolerance) throw new Error('FreeCAD ISO M6 tap-drill evidence is invalid.')
if (modeled.modeled !== true || modeled.threadDirection !== 'Left' || Math.abs(modeled.diameter - 5.026) > oracle.tolerance || Math.abs(modeled.volume - 3820.1907618181585) > oracle.tolerance || modeled.faces <= tap.faces || modeled.edges <= tap.edges || !(modeled.volume < tap.volume)) throw new Error('FreeCAD ISO M6 modeled-thread evidence is invalid.')
const chrome = await load('config/chrome-partdesign-transform-verification.json')
const featureTransforms = chrome.operations?.filter((entry) => entry.transformMode === 'Features') ?? []
const threadedHoles = chrome.operations?.filter((entry) => entry.command === 'hole' && entry.threaded === true) ?? []
if (chrome.status !== 'pass' || chrome.operations?.length !== 14 || chrome.operations.some((entry) => entry.solids !== 1 || !(entry.volume > 0)) || featureTransforms.length !== 2 || featureTransforms.some((entry) => entry.originals?.length !== 1) || threadedHoles.length !== 2 || threadedHoles[0].modelThread !== false || threadedHoles[1].modelThread !== true || threadedHoles[1].threadDirection !== 'Left' || chrome.afterRelease?.shapeCount !== 0 || chrome.afterRelease?.kernelReferenceCount !== 0) throw new Error('Chrome PartDesign transform/thread evidence is invalid.')
const nativePaths = new Map([
['linear-pattern', 'config/chrome-native-linear-pattern-history-verification.json'],
['polar-pattern', 'config/chrome-native-polar-pattern-history-verification.json'],
['mirrored', 'config/chrome-native-mirrored-history-verification.json'],
['multi-transform', 'config/chrome-native-multi-transform-history-verification.json'],
])
const nativeHistory = {}
for (const [operation, path] of nativePaths) {
const report = await load(path)
if (report.status !== 'pass' || report.nativeCapabilities?.operations?.includes(operation) !== true || report.history?.recordCount < 1 || report.afterRelease?.shapeCount !== 0 || report.afterRelease?.kernelReferenceCount !== 0) throw new Error(`Chrome native ${operation} history evidence is invalid.`)
nativeHistory[operation] = report.history.recordCount
}
console.log(JSON.stringify({ status: 'freecad-partdesign-transform-oracle-pass', baselineId: oracle.baselineId, summary: oracle.summary, featureTransforms: featureTransforms.map((entry) => ({ command: entry.command, originals: entry.originals, volume: entry.volume })), threadedHoles: threadedHoles.map((entry) => ({ size: entry.threadSize, modeled: entry.modelThread, direction: entry.threadDirection, volume: entry.volume })), nativeHistory }, null, 2))