import { describe, expect, it } from "vitest"; import { defineToolcraft } from "../schema/define-toolcraft"; import type { ToolcraftAppSchema } from "../schema/types"; import { TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE, deriveToolcraftModelPerformancePaths, } from "./model-import-performance-workload"; function schemaWithControls( controls: ToolcraftAppSchema["panels"]["controls"] extends infer T ? T extends { sections: readonly (infer Section)[] } ? Section extends { controls: infer Controls } ? Controls : never : never : never, ) { return defineToolcraft({ canvas: { enabled: true, sizing: { mode: "editable-output" } }, panels: { controls: { sections: [{ controls, title: "Source" }], title: "Controls", }, }, }); } describe("Toolcraft model performance workload", () => { it("derives import, analysis/repair, and orbit paths from normalized model limits", () => { const schema = schemaWithControls({ orientation: { defaultValue: { position: [0, 0, 5], up: [0, 1, 0] }, keyframeable: false, label: false, target: "view.orientation", type: "orientationGizmo", }, source: { assetKind: "model", modelFormats: ["glb", "ply"], modelLimits: { maxBundleFiles: 5, maxDecodedBytes: 1_000_000, maxEstimatedWorkerBytes: 16_000_000, maxNodes: 10, maxPrimitives: 20, maxSourceBytes: 50_000, maxTriangles: 1_000, maxVertices: 2_000, }, target: "source.model", topologyProfile: "solid-mesh", type: "fileDrop", }, }); const paths = deriveToolcraftModelPerformancePaths(schema); expect(paths.map((path) => [path.kind, path.profile])).toEqual([ ["import", "batch-responsive"], ["analysis-repair", "batch-responsive"], ["orbit", "interactive-continuous"], ]); expect(paths[0]).toMatchObject({ formats: ["glb", "ply"], id: "runtime-model:source.model:import", target: "source.model", topologyProfile: "solid-mesh", }); expect(paths[0]?.dimensions).toEqual([ expect.objectContaining({ configuredMaximumValue: 5, developmentValue: 4, effectiveMaximumValue: 5, id: "model-bundle-files", limit: "maxBundleFiles", maximumValue: 5, targetPressure: TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE, unit: "files", }), expect.objectContaining({ developmentValue: 40_000, id: "model-source-bytes", limit: "maxSourceBytes", maximumValue: 50_000, targetPressure: TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE, unit: "bytes", }), expect.objectContaining({ developmentValue: 38_410, effectiveMaximumValue: 48_012, id: "model-decoded-bytes", }), expect.objectContaining({ developmentValue: 12_800_000, id: "model-worker-bytes", }), expect.objectContaining({ developmentValue: 8, id: "model-nodes" }), expect.objectContaining({ developmentValue: 16, id: "model-primitives" }), expect.objectContaining({ developmentValue: 800, id: "model-triangles" }), expect.objectContaining({ developmentValue: 1_600, id: "model-vertices" }), ]); expect(paths[2]?.dimensions.map((dimension) => dimension.id)).toEqual([ "model-nodes", "model-primitives", "model-triangles", "model-vertices", ]); expect(paths[0]?.development).toMatchObject({ combinedPressureRatio: TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE, kind: "development", values: { "model-source-bytes": 40_000, "model-triangles": 800, "model-vertices": 1_600, }, }); expect(paths[0]?.maximum.combinedPressureRatio).toBe(1); expect(paths[0]?.appearance.configured).toEqual({ textureBytes: 33_554_432, textureCount: 256, textureDimension: 8_192, texturePixels: 33_554_432, }); expect(paths[0]?.appearance.effectiveMaximum.combinedWorkerBytes) .toBeLessThanOrEqual(16_000_000); expect(paths[0]?.appearance.fitsWorkerLimit).toBe(true); expect(paths[0]?.appearance.development.combinedWorkerBytes) .toBeLessThan(paths[0]!.appearance.effectiveMaximum.combinedWorkerBytes); expect(Object.isFrozen(paths)).toBe(true); expect(Object.isFrozen(paths[0]?.dimensions)).toBe(true); }); it("treats folders and ZIP packages as multi-file workloads for every format", () => { const singleFileSchema = schemaWithControls({ source: { assetKind: "model", modelFormats: ["glb", "obj"], target: "source.model", type: "fileDrop", }, }); const bundledSchema = schemaWithControls({ source: { assetKind: "model", modelFormats: ["gltf"], target: "source.model", type: "fileDrop", }, }); const bundleDimension = (schema: ReturnType) => deriveToolcraftModelPerformancePaths(schema)[0]?.dimensions.find( (dimension) => dimension.id === "model-bundle-files", ); expect(bundleDimension(singleFileSchema)?.effectiveMaximumValue).toBe(32); expect(bundleDimension(bundledSchema)?.effectiveMaximumValue).toBe(32); }); it("projects raw topology ceilings onto the worker-memory envelope before applying 80% pressure", () => { const schema = schemaWithControls({ source: { assetKind: "model", target: "source.model", type: "fileDrop", }, }); const analysisPath = deriveToolcraftModelPerformancePaths(schema).find( (path) => path.kind === "analysis-repair", ); const triangles = analysisPath?.dimensions.find( (dimension) => dimension.id === "model-triangles", ); expect(triangles?.configuredMaximumValue).toBe(1_000_000); expect(triangles?.effectiveMaximumValue).toBeLessThan(1_000_000); expect(triangles?.developmentValue).toBeLessThanOrEqual( triangles?.effectiveMaximumValue ?? 0, ); expect( (triangles?.developmentValue ?? 0) / (triangles?.effectiveMaximumValue ?? 1), ).toBeGreaterThanOrEqual(TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE); }); it("projects node pressure through the canonical encode memory envelope", () => { const schema = schemaWithControls({ source: { assetKind: "model", target: "source.model", type: "fileDrop", }, }); const nodeDimension = deriveToolcraftModelPerformancePaths(schema)[0] ?.dimensions.find((dimension) => dimension.id === "model-nodes"); expect(nodeDimension?.configuredMaximumValue).toBe(10_000); expect(nodeDimension?.effectiveMaximumValue).toBeLessThan(8_000); expect(nodeDimension?.developmentValue).toBeLessThanOrEqual( nodeDimension?.effectiveMaximumValue ?? 0, ); }); it("uses the nearest admissible integer without dropping below the 80% target", () => { const schema = schemaWithControls({ source: { assetKind: "model", modelLimits: { maxBundleFiles: 1, maxDecodedBytes: 3, maxEstimatedWorkerBytes: 3, maxNodes: 3, maxPrimitives: 3, maxSourceBytes: 3, maxTriangles: 3, maxVertices: 3, }, target: "source.model", type: "fileDrop", }, }); for (const path of deriveToolcraftModelPerformancePaths(schema)) { expect(path.appearance.fitsWorkerLimit).toBe(false); for (const dimension of path.dimensions) { expect(dimension.developmentValue).toBeLessThanOrEqual( dimension.maximumValue, ); expect(dimension.developmentValue / dimension.maximumValue).toBeGreaterThanOrEqual( TOOLCRAFT_MODEL_PERFORMANCE_DEVELOPMENT_PRESSURE, ); } } }); it("does not invent model workloads for non-model uploaders", () => { const schema = schemaWithControls({ source: { assetKind: "image", target: "source.image", type: "fileDrop", }, }); expect(deriveToolcraftModelPerformancePaths(schema)).toEqual([]); }); it("only derives orbit pressure when the built-in orientation control exists", () => { const schema = schemaWithControls({ source: { assetKind: "model", target: "source.model", type: "fileDrop", }, }); expect( deriveToolcraftModelPerformancePaths(schema).map((path) => path.kind), ).toEqual(["import", "analysis-repair"]); }); });