52 lines
4.7 KiB
JavaScript
52 lines
4.7 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import assert from 'node:assert/strict';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { loadWasmProbe } from './wasm-probe-runtime.mjs';
|
|
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
|
|
const output=path.join(root,'docs/current/user-tests-20260915',`ifc-native-${new Date().toISOString().replace(/[:.]/g,'-')}`);
|
|
fs.mkdirSync(output,{recursive:true});
|
|
const fixture=path.join(root,'FreeCADBaseLib/sources/src/Qt-5.15.13/qt3d/src/3rdparty/assimp/src/test/models/IFC/AC14-FZK-Haus.ifc');
|
|
const log=message=>fs.appendFileSync(path.join(output,'native.log'),String(message)+'\n');
|
|
const results=[];
|
|
console.log(output);
|
|
try {
|
|
const {kernel}=await loadWasmProbe(path.join(root,'freecad-source/build-web/configure/bin'),'FreeCADWebPartBoxProbe',{print:log,printErr:log});
|
|
const dispatch=(command,parameters,document='IfcValidation')=>{
|
|
const started=performance.now();
|
|
const reply=JSON.parse(kernel.ccall('fc_web_dispatch_json','string',['string'],[JSON.stringify({cmd:'part.viewCommand',args:{schema:'freecad-web/document-view/v1',owner:'PartBox',document,command,parameters:{...parameters,documentId:document}}})]));
|
|
results.push({command,seconds:(performance.now()-started)/1000,reply});
|
|
fs.writeFileSync(path.join(output,'results.json'),JSON.stringify(results,null,2)+'\n');
|
|
console.log(JSON.stringify({command,ok:reply.ok,error:reply.error,seconds:results.at(-1).seconds}));
|
|
assert.equal(reply.ok,true,JSON.stringify(reply));return reply.result;
|
|
};
|
|
const opened=dispatch('Std_Open',{operation:'open',files:[{filename:'AC14-FZK-Haus.ifc',fileData:fs.readFileSync(fixture).toString('base64')}]});
|
|
assert.equal(opened.errors.length,0,JSON.stringify(opened.errors));
|
|
assert.ok(opened.opened[0].documents[0].objectCount>20);
|
|
const doc=opened.activeDocument;
|
|
const inspect=dispatch('Std_CommandLine',{operation:'submit',source:`import json; d=App.getDocument('${doc}'); print(json.dumps({'objects':len(d.Objects),'shapes':sum(1 for o in d.Objects if o.isDerivedFrom('Part::Feature') and not o.Shape.isNull()),'groups':sum(1 for o in d.Objects if o.isDerivedFrom('App::DocumentObjectGroup')),'volume':sum(o.Shape.Volume for o in d.Objects if o.isDerivedFrom('Part::Feature')),'features':[{'name':o.Name,'guid':o.IfcGlobalId,'volume':o.Shape.Volume,'area':o.Shape.Area,'faces':len(o.Shape.Faces),'bounds':[o.Shape.BoundBox.XMin,o.Shape.BoundBox.YMin,o.Shape.BoundBox.ZMin,o.Shape.BoundBox.XMax,o.Shape.BoundBox.YMax,o.Shape.BoundBox.ZMax]} for o in d.Objects if o.isDerivedFrom('Part::Feature')]}))`},doc);
|
|
assert.equal(inspect.stderr,'');
|
|
const state=JSON.parse(inspect.stdout.trim());assert.ok(state.shapes>20);assert.ok(state.groups>=3);assert.ok(state.volume>0);
|
|
const baseline=JSON.parse(fs.readFileSync(path.join(root,'docs/current/user-tests-20260915/ifc-geometry-baseline.json'))).state;
|
|
assert.equal(state.objects,baseline.objects,'Optimization changed the document object count');
|
|
assert.equal(state.shapes,baseline.features.length,'Optimization changed the native feature count');
|
|
assert.equal(state.groups,baseline.groups,'Optimization changed spatial groups');
|
|
const comparisons=[];
|
|
for(const original of baseline.features){
|
|
const actual=state.features.find(f=>f.name===original.name);
|
|
assert.ok(actual,`Missing feature ${original.name}`);assert.equal(actual.guid,original.guid);
|
|
const delta={name:original.name,volume:Math.abs(actual.volume-original.volume),area:Math.abs(actual.area-original.area),
|
|
bounds:Math.max(...actual.bounds.map((v,i)=>Math.abs(v-original.bounds[i]))),faces:actual.faces-original.faces};
|
|
comparisons.push(delta);
|
|
fs.writeFileSync(path.join(output,'geometry-comparison.json'),JSON.stringify(comparisons,null,2)+'\n');
|
|
assert.ok(delta.volume<=Math.max(1e-5,Math.abs(original.volume)*1e-7),`${original.name} volume changed: ${delta.volume}`);
|
|
assert.ok(delta.area<=Math.max(1e-5,Math.abs(original.area)*1e-7),`${original.name} area changed: ${delta.area}`);
|
|
assert.ok(delta.bounds<=1e-5,`${original.name} bounds changed: ${delta.bounds}`);
|
|
}
|
|
const saved=dispatch('Std_SaveAs',{filename:'/tmp/IfcValidation.FCStd'},doc);
|
|
assert.ok(saved.files[0].contentsBase64.length>1000);
|
|
fs.writeFileSync(path.join(output,'IfcValidation.FCStd'),Buffer.from(saved.files[0].contentsBase64,'base64'));
|
|
fs.writeFileSync(path.join(output,'summary.json'),JSON.stringify({status:'passed',state,scope:'Native IFC import and FCStd save; not browser acceptance'},null,2)+'\n');
|
|
} catch(error) {fs.writeFileSync(path.join(output,'failure.json'),JSON.stringify({status:'failed',error:String(error)},null,2)+'\n');console.error(String(error));process.exitCode=1;}
|
|
process.exit(process.exitCode??0);
|