/ proof-of-concept / plate-dynamics-lab
Sign in
proof-of-concept / plate-dynamics-lab
plate-dynamics-lab / packages / core / test / generate.test.ts
108 lines · 3.8 KBCodeBlameHistory
80c0b6dPlate dynamics lab: plates in realizable mounts under gravity, explicit finite differences on WebGPUJeremy Magland 1import { describe, expect, it } from "vitest";
2import {
3 FD_METHOD,
4 SCENARIO_PRESETS,
5 buildRunBundle,
6 formatNumber,
7 generateParamsBlock,
8 isPlainStruct,
9 withEdits,
10 LIBRARY_FILES,
11 validateSpec,
12} from "../src/index";
13import { runner, testSpec } from "./helpers";
15describe("source generation and editing", () => {
16 it("formats numbers as exact, readable MATLAB literals", () => {
17 expect(formatNumber(200e9)).toBe("200e9");
18 expect(formatNumber(0.002)).toBe("0.002");
19 expect(formatNumber(44100)).toBe("44100");
20 expect(formatNumber(1e-3)).toBe("0.001");
21 expect(formatNumber(2.5e-7)).toBe("250e-9");
22 expect(formatNumber(7850)).toBe("7850");
23 expect(Number(formatNumber(68.9e9))).toBe(68.9e9);
24 expect(formatNumber(-3)).toBe("-3");
25 });
27 it("round-trips the spec through the params block", async () => {
28 const spec = testSpec();
29 const block = generateParamsBlock(spec);
30 const bundle = {
31 files: [{ name: "p.m", source: block }, ...LIBRARY_FILES],
32 entry: "p.m",
33 resultVariable: "params",
34 };
35 const run = await runner.run({ bundle });
36 expect(run.ok).toBe(true);
37 if (!run.ok || !isPlainStruct(run.value)) return;
38 const plate = run.value.fields.plate;
39 const mat = run.value.fields.material;
40 const mount = run.value.fields.mount;
41 if (!isPlainStruct(plate) || !isPlainStruct(mat) || !isPlainStruct(mount))
42 throw new Error("params fields are not structs");
43 expect(plate.fields.h).toBe(spec.plate.h);
44 expect(mat.fields.E).toBe(spec.material.E);
45 expect(mat.fields.name).toBe(spec.material.name);
46 expect(mount.fields.type).toBe("thread");
47 });
49 it("writes every mount as a struct numbl accepts", async () => {
50 for (const sc of SCENARIO_PRESETS) {
51 const block = generateParamsBlock(sc.spec);
52 const run = await runner.run({
53 bundle: {
54 files: [
55 { name: "p.m", source: block + "\nP = plate_setup(params);\n" },
56 ...LIBRARY_FILES,
57 ],
58 entry: "p.m",
59 resultVariable: "P",
60 },
61 });
62 expect(run.ok, `${sc.id}: ${run.ok ? "" : run.error}`).toBe(true);
63 }
64 });
66 it("runs the edited source, and surfaces numbl errors with file and line", async () => {
67 const spec = testSpec();
68 const bundle = buildRunBundle(spec, FD_METHOD);
69 const main = bundle.files.find((f) => f.name === "main.m")!.source;
70 const edited = withEdits(bundle, {
71 "main.m": main.replace(
72 "result = plate_fd(params);",
73 "result = plate_fd(params)\nresult = undefined_function_xyz(1);",
74 ),
75 });
76 const run = await runner.run({ bundle: edited });
77 expect(run.ok).toBe(false);
78 if (run.ok) return;
79 expect(run.error).toMatch(/undefined_function_xyz/);
80 expect(run.error).toMatch(/main\.m/);
81 });
83 it("reports a missing result variable rather than an empty screen", async () => {
84 const spec = testSpec();
85 const bundle = buildRunBundle(spec, FD_METHOD);
86 const edited = withEdits(bundle, { "main.m": "x = 1;" });
87 const run = await runner.run({ bundle: edited });
88 expect(run.ok).toBe(false);
89 if (!run.ok) expect(run.error).toMatch(/result/);
90 });
92 it("validates obviously bad specs", () => {
93 const spec = testSpec();
94 spec.probe.x = 10;
95 spec.fd.cfl = 1.2;
96 const issues = validateSpec(spec);
97 expect(issues.some((i) => i.path === "probe" && i.severity === "error")).toBe(true);
98 expect(issues.some((i) => i.path === "fd.cfl" && i.severity === "warning")).toBe(true);
99 const two = testSpec();
100 two.mount = { type: "threads", x1: 0.2, y1: 0.19, x2: 0.28, y2: 0.19, length: 0.3 };
101 expect(validateSpec(two).some((i) => /slack/.test(i.message))).toBe(true);
102 for (const sc of SCENARIO_PRESETS)
103 expect(
104 validateSpec(sc.spec).filter((i) => i.severity === "error"),
105 sc.id,
106 ).toEqual([]);
107 });
108});
↑↓ move↵openescclose