feat: define versioned sketch solver protocol
This commit is contained in:
@@ -10,6 +10,7 @@ import { createEdgeSubshapeRefs, createSubshapeRefs, createVertexSubshapeRefs, m
|
||||
import { createPersistedTopoRef, migrateTopoRefs, parseTopoRef, resolveTopoRef, serializeTopoRef } from '../src/facade/topologyReferences'
|
||||
import { captureSignatureTopologyHistory } from '../src/facade/topologyHistory'
|
||||
import { createSketch, solveSketch } from '../src/facade/sketcher'
|
||||
import { BasicSketchSolverProvider, SKETCH_SOLVER_PROTOCOL_VERSION, SketchSolverCoordinator, SketchSolverUnavailableError, UnavailablePlanegcsProvider, runSketchSolverReplay, type SketchSolverProvider, type SketchSolverRequest } from '../src/facade/sketchSolverProtocol'
|
||||
import { createFacadeGeometryRecomputeExecutor, executeFacadeRecomputeNode, RecomputeCoordinator, type RecomputeGeometryRuntime } from '../src/facade/recomputeEngine'
|
||||
import { inspectFcstdArchive } from '../src/facade/fcstd'
|
||||
import { assertShapeHandleIntegrity, normalizeBitbybitMesh, validateBooleanUnionInput, validateBoxInput, validateChamferInput, validateConeInput, validateCylinderInput, validateFilletInput, validatePadInput, validatePlacementInput, validatePlanarProfile, validateRevolutionInput, validateSphereInput } from '../src/facade/geometryRuntime'
|
||||
@@ -254,6 +255,53 @@ test('Sketcher solver supports diameter, symmetric and tangent constraints at th
|
||||
assert.equal((result.snapshot.geometry.find((geometry) => geometry.id === 'circle-1') as Extract<typeof result.snapshot.geometry[number], { type: 'circle' }>).center.y, 2)
|
||||
})
|
||||
|
||||
test('sketch solver protocol exposes honest capabilities and deterministic replay', async () => {
|
||||
const provider = new BasicSketchSolverProvider()
|
||||
assert.deepEqual(provider.capabilities().engine, 'typescript-basic')
|
||||
assert.equal(provider.capabilities().compatibility, 'experimental')
|
||||
const fixture = createSketch('protocol-sketch', [{ id: 'line-1', type: 'line', start: { x: 0, y: 0 }, end: { x: 4, y: 2 } }], [
|
||||
{ id: 'horizontal-1', type: 'horizontal', geometryId: 'line-1' },
|
||||
])
|
||||
const replay = await runSketchSolverReplay(provider, [{
|
||||
id: 'basic-horizontal',
|
||||
request: { requestId: 'replay-1', documentId: 'doc', documentVersion: 1, snapshot: fixture },
|
||||
expected: { status: 'under-constrained', degreesOfFreedom: 3, maxResidual: 1e-7 },
|
||||
}])
|
||||
assert.deepEqual(replay, [{ id: 'basic-horizontal', passed: true, differences: [] }])
|
||||
|
||||
const unavailable = new UnavailablePlanegcsProvider()
|
||||
assert.equal(unavailable.capabilities().availability, 'unavailable')
|
||||
assert.equal(unavailable.capabilities().engine, 'planegcs-wasm')
|
||||
await assert.rejects(() => unavailable.solve({} as SketchSolverRequest, new AbortController().signal), SketchSolverUnavailableError)
|
||||
})
|
||||
|
||||
test('sketch solver coordinator rejects cancelled and stale generations', async () => {
|
||||
let documentVersion = 1
|
||||
let releaseFirst: (() => void) | undefined
|
||||
const basic = new BasicSketchSolverProvider()
|
||||
const delayed: SketchSolverProvider = {
|
||||
capabilities: () => basic.capabilities(),
|
||||
solve: (request, signal) => new Promise((resolve, reject) => {
|
||||
const release = () => basic.solve(request, signal).then(resolve, reject)
|
||||
if (request.requestId === 'first') releaseFirst = release
|
||||
else release()
|
||||
}),
|
||||
}
|
||||
const coordinator = new SketchSolverCoordinator(() => documentVersion)
|
||||
const snapshot = createSketch('coordinator')
|
||||
const first = coordinator.solve(delayed, { requestId: 'first', documentId: 'doc', documentVersion: 1, snapshot })
|
||||
const second = coordinator.solve(delayed, { requestId: 'second', documentId: 'doc', documentVersion: 1, snapshot })
|
||||
releaseFirst?.()
|
||||
assert.equal((await first).status, 'cancelled')
|
||||
assert.equal((await second).status, 'completed')
|
||||
|
||||
documentVersion = 2
|
||||
const stale = await coordinator.solve(basic, { requestId: 'stale', documentId: 'doc', documentVersion: 1, snapshot })
|
||||
assert.equal(stale.status, 'stale')
|
||||
assert.equal(stale.generation, 3)
|
||||
assert.equal(SKETCH_SOLVER_PROTOCOL_VERSION, 1)
|
||||
})
|
||||
|
||||
test('sketcher operations are facade transactions and survive the project fallback store', async () => {
|
||||
const facade = createMockFacade()
|
||||
const before = facade.app.document.getActive().version
|
||||
|
||||
Reference in New Issue
Block a user