ihsm 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +161 -8
  2. package/lib/cjs/index.d.ts +517 -56
  3. package/lib/cjs/index.js +279 -5
  4. package/lib/cjs/index.js.map +1 -1
  5. package/lib/cjs/internal/defs.private.d.ts +10 -0
  6. package/lib/cjs/internal/dispatch.debug.js +2 -1
  7. package/lib/cjs/internal/dispatch.debug.js.map +1 -1
  8. package/lib/cjs/internal/dispatch.production.js +2 -1
  9. package/lib/cjs/internal/dispatch.production.js.map +1 -1
  10. package/lib/cjs/internal/dispatch.trace.js +8 -1
  11. package/lib/cjs/internal/dispatch.trace.js.map +1 -1
  12. package/lib/cjs/internal/hsm.d.ts +7 -1
  13. package/lib/cjs/internal/hsm.js +36 -3
  14. package/lib/cjs/internal/hsm.js.map +1 -1
  15. package/lib/cjs/internal/lookup.d.ts +15 -0
  16. package/lib/cjs/internal/lookup.js +32 -0
  17. package/lib/cjs/internal/lookup.js.map +1 -0
  18. package/lib/cjs/testing.d.ts +279 -0
  19. package/lib/cjs/testing.js +392 -0
  20. package/lib/cjs/testing.js.map +1 -0
  21. package/lib/esm/index.d.ts +517 -56
  22. package/lib/esm/index.js +275 -5
  23. package/lib/esm/index.js.map +1 -1
  24. package/lib/esm/internal/defs.private.d.ts +10 -0
  25. package/lib/esm/internal/dispatch.debug.js +2 -1
  26. package/lib/esm/internal/dispatch.debug.js.map +1 -1
  27. package/lib/esm/internal/dispatch.production.js +2 -1
  28. package/lib/esm/internal/dispatch.production.js.map +1 -1
  29. package/lib/esm/internal/dispatch.trace.js +8 -1
  30. package/lib/esm/internal/dispatch.trace.js.map +1 -1
  31. package/lib/esm/internal/hsm.d.ts +7 -1
  32. package/lib/esm/internal/hsm.js +36 -3
  33. package/lib/esm/internal/hsm.js.map +1 -1
  34. package/lib/esm/internal/lookup.d.ts +15 -0
  35. package/lib/esm/internal/lookup.js +29 -0
  36. package/lib/esm/internal/lookup.js.map +1 -0
  37. package/lib/esm/testing.d.ts +279 -0
  38. package/lib/esm/testing.js +370 -0
  39. package/lib/esm/testing.js.map +1 -0
  40. package/package.json +20 -4
@@ -0,0 +1,370 @@
1
+ /**
2
+ * `ihsm/testing` — deterministic-simulation testing utilities for ihsm.
3
+ *
4
+ * This entry point is **separate from the core runtime** (`ihsm`): the mock-port machinery,
5
+ * the manual virtual clock, and the full-access test actor live here so they are never bundled
6
+ * into production code that only imports `ihsm`. Import test helpers from `ihsm/testing`:
7
+ *
8
+ * ```ts
9
+ * import { makeHsm, TopState } from 'ihsm'; // production code
10
+ * import { makeTestActor, mock, TestPort } from 'ihsm/testing'; // tests only
11
+ * ```
12
+ *
13
+ * For convenience this module also re-exports the entire core API, so a test file may import
14
+ * everything it needs from `ihsm/testing` alone.
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+ import { BasePort, TraceLevel, defaultDispatchErrorCallback, defaultInitialize, defaultTraceWriter, makeHsm } from './index.js';
19
+ export * from './index.js';
20
+ export class TestPort extends BasePort {
21
+ _messages = [];
22
+ _preloads = new Map();
23
+ _now = 0;
24
+ _timerSeq = 0;
25
+ _timers = [];
26
+ _cancelled = new Set();
27
+ _randomQueue = [];
28
+ _cryptoRandomQueue = [];
29
+ _uuidQueue = [];
30
+ _byteQueue = [];
31
+ /**
32
+ * Append an entry to the recorded message log (for assertions / golden traces).
33
+ *
34
+ * Callable both from inside the mock (e.g. a port method logging its outbound call) and from a
35
+ * test (e.g. a `Disposable.dispose` closure recording its own teardown into the trace).
36
+ *
37
+ * @param event - Event name or free-form label (e.g. `'connect'`, `'attempt 1: ok'`)
38
+ * @param payload - Optional values associated with the entry
39
+ */
40
+ record(event, ...payload) {
41
+ this._messages.push({ event, payload: [...payload] });
42
+ }
43
+ _slot(name) {
44
+ let slot = this._preloads.get(name);
45
+ if (slot === undefined) {
46
+ slot = { queue: [], calls: [] };
47
+ this._preloads.set(name, slot);
48
+ }
49
+ return slot;
50
+ }
51
+ /** @internal Set the persistent implementation for a stubbed method (used by `method.default`). */
52
+ _stubDefault(name, impl) {
53
+ this._slot(name).fallback = impl;
54
+ }
55
+ /** @internal Queue a one-shot implementation for a stubbed method (used by `method.once`). */
56
+ _stubOnce(name, impl) {
57
+ this._slot(name).queue.push(impl);
58
+ }
59
+ /** @internal Clear a stubbed method's queued/persistent implementations and recorded calls (`method.reset`). */
60
+ _stubReset(name) {
61
+ const slot = this._slot(name);
62
+ slot.queue.length = 0;
63
+ slot.fallback = undefined;
64
+ slot.calls.length = 0;
65
+ }
66
+ /** @internal The live, typed list of argument tuples a stubbed method was called with (`method.calls`). */
67
+ _stubCalls(name) {
68
+ return this._slot(name).calls;
69
+ }
70
+ /**
71
+ * @internal Consume the next implementation for a stubbed method. Installed as the body of every
72
+ * `@`{@link mock}-stubbed method by {@link makeTestPort}; not called directly.
73
+ *
74
+ * The call is recorded first (globally in {@link trace} and in the method's {@link Stubbed.calls}),
75
+ * then one-shot stubs (queued via `method.once`) are consumed in order; otherwise the persistent
76
+ * `method.default` implementation runs. With neither set, a {@link PreloadError} naming the method
77
+ * is thrown.
78
+ *
79
+ * @param name - Port method name
80
+ * @param args - Arguments the machine passed to the method
81
+ * @throws {@link PreloadError} if nothing was stubbed for `name`
82
+ */
83
+ _consumePreload(name, args) {
84
+ const slot = this._slot(name);
85
+ slot.calls.push(args); // typed per-method record
86
+ this.record(name, ...args); // global golden-trace record, even if unstubbed
87
+ const impl = slot.queue.shift() ?? slot.fallback;
88
+ if (impl === undefined) {
89
+ throw new PreloadError(name);
90
+ }
91
+ return impl(...args);
92
+ }
93
+ /** Every recorded message, in order. */
94
+ get messages() {
95
+ return this._messages;
96
+ }
97
+ /** Just the recorded event names, in order. */
98
+ get events() {
99
+ return this._messages.map(m => m.event);
100
+ }
101
+ /** Rendered `event` / `event:arg,arg` strings — convenient for `deep.equal` / `include`. */
102
+ get trace() {
103
+ return this._messages.map(m => (m.payload.length > 0 ? `${m.event}:${m.payload.join(',')}` : m.event));
104
+ }
105
+ /** The most recently recorded message, or `undefined`. */
106
+ get last() {
107
+ return this._messages[this._messages.length - 1];
108
+ }
109
+ /** Number of recorded messages. */
110
+ get count() {
111
+ return this._messages.length;
112
+ }
113
+ /** Clear the recorded message log. */
114
+ clear() {
115
+ this._messages.length = 0;
116
+ }
117
+ _sortTimers() {
118
+ this._timers.sort((a, b) => a.at - b.at || a.id - b.id);
119
+ }
120
+ /** @inheritdoc Port.setTimeout — backed by the virtual clock; fire with {@link TestPort.advance | advance}. */
121
+ setTimeout(callback, millis) {
122
+ const id = ++this._timerSeq;
123
+ this._timers.push({ id, at: this._now + Math.max(0, millis ?? 0), callback });
124
+ this._sortTimers();
125
+ return id;
126
+ }
127
+ /** @inheritdoc Port.clearTimeout */
128
+ clearTimeout(id) {
129
+ if (id === undefined) {
130
+ return;
131
+ }
132
+ this._cancelled.add(id);
133
+ const index = this._timers.findIndex(timer => timer.id === id);
134
+ if (index >= 0) {
135
+ this._timers.splice(index, 1);
136
+ }
137
+ }
138
+ /** @inheritdoc Port.setInterval — backed by the virtual clock; fire with {@link TestPort.advance | advance}. */
139
+ setInterval(callback, millis) {
140
+ const id = ++this._timerSeq;
141
+ const repeat = Math.max(0, millis ?? 0);
142
+ this._timers.push({ id, at: this._now + repeat, callback, repeat });
143
+ this._sortTimers();
144
+ return id;
145
+ }
146
+ /** @inheritdoc Port.clearInterval */
147
+ clearInterval(id) {
148
+ this.clearTimeout(id);
149
+ }
150
+ /**
151
+ * Advance the virtual clock by `millis`, firing every timer whose deadline is reached, in
152
+ * deadline order. Timers scheduled by a fired callback within the same window are **not** run
153
+ * until a later `advance` — mirroring how a deferred re-schedule lands on the next run-to-completion turn.
154
+ *
155
+ * @param millis - Virtual milliseconds to advance (negative values are clamped to `0`)
156
+ */
157
+ advance(millis) {
158
+ const target = this._now + Math.max(0, millis);
159
+ const due = this._timers.filter(timer => timer.at <= target && !this._cancelled.has(timer.id));
160
+ this._timers.splice(0, due.length);
161
+ for (const timer of due) {
162
+ this._now = timer.at;
163
+ timer.callback();
164
+ if (timer.repeat !== undefined && !this._cancelled.has(timer.id)) {
165
+ this._timers.push({ id: timer.id, at: this._now + timer.repeat, callback: timer.callback, repeat: timer.repeat });
166
+ }
167
+ }
168
+ this._sortTimers();
169
+ this._now = target;
170
+ }
171
+ /** Current virtual time, in milliseconds since construction. */
172
+ get now() {
173
+ return this._now;
174
+ }
175
+ /** Number of timers still pending (not yet fired or disposed). */
176
+ get pending() {
177
+ return this._timers.length;
178
+ }
179
+ /** Queue values returned by successive {@link TestPort.random | random} calls (FIFO). */
180
+ feedRandom(...values) {
181
+ this._randomQueue.push(...values);
182
+ }
183
+ /** Queue values returned by successive {@link TestPort.cryptoRandom | cryptoRandom} calls (FIFO). */
184
+ feedCryptoRandom(...values) {
185
+ this._cryptoRandomQueue.push(...values);
186
+ }
187
+ /** Queue values returned by successive {@link TestPort.randomUUID | randomUUID} calls (FIFO). */
188
+ feedUUID(...values) {
189
+ this._uuidQueue.push(...values);
190
+ }
191
+ /** Queue bytes used to fill arrays in successive {@link TestPort.getRandomValues | getRandomValues} calls (FIFO). */
192
+ feedRandomBytes(...bytes) {
193
+ this._byteQueue.push(...bytes);
194
+ }
195
+ /** Clear all scripted random queues ({@link TestPort.feedRandom | feedRandom} / {@link TestPort.feedCryptoRandom | feedCryptoRandom} / …). */
196
+ resetRandom() {
197
+ this._randomQueue.length = 0;
198
+ this._cryptoRandomQueue.length = 0;
199
+ this._uuidQueue.length = 0;
200
+ this._byteQueue.length = 0;
201
+ }
202
+ /** @inheritdoc RandomService.random — queued values only; returns `0` when empty (never calls `Math.random`). */
203
+ random() {
204
+ const next = this._randomQueue.shift();
205
+ return next ?? 0;
206
+ }
207
+ /** @inheritdoc RandomService.cryptoRandom — queued values only; returns `0` when empty (never calls `crypto.random`). */
208
+ cryptoRandom() {
209
+ const next = this._cryptoRandomQueue.shift();
210
+ return next ?? 0;
211
+ }
212
+ /** @inheritdoc RandomService.randomUUID — queued values only; never calls `crypto.randomUUID`. */
213
+ randomUUID() {
214
+ return this._uuidQueue.shift() ?? '00000000-0000-0000-0000-000000000000';
215
+ }
216
+ /** @inheritdoc RandomService.getRandomValues — queued bytes only; never calls `crypto.getRandomValues`. */
217
+ getRandomValues(array) {
218
+ const view = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
219
+ for (let index = 0; index < view.length; index++) {
220
+ view[index] = this._byteQueue.shift() ?? 0;
221
+ }
222
+ return array;
223
+ }
224
+ }
225
+ /**
226
+ * Thrown when an abstract `@`{@link mock} port method is called but the test scripted no
227
+ * implementation for it. The message names the method so the fix is obvious.
228
+ *
229
+ * @category Testing
230
+ */
231
+ export class PreloadError extends Error {
232
+ constructor(method) {
233
+ super(`ihsm: '${method}()' was called but not stubbed — script it first with port.${method}.default(...) or port.${method}.once(...)`);
234
+ this.name = 'PreloadError';
235
+ }
236
+ }
237
+ /** Property names the auto-stub must never synthesize — JS/test-framework probes and built-in port services. */
238
+ const NON_STUB_PROPS = new Set(['then', 'catch', 'finally', 'toJSON', 'inspect', 'asymmetricMatch', '$$typeof', 'nodeType', 'setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'random', 'cryptoRandom', 'randomUUID', 'getRandomValues', 'advance', 'now', 'pending', 'feedRandom', 'feedCryptoRandom', 'feedUUID', 'feedRandomBytes', 'resetRandom']);
239
+ function buildMethodStub(target, name) {
240
+ const stub = (...args) => target._consumePreload(name, args);
241
+ stub.default = (impl) => {
242
+ target._stubDefault(name, impl);
243
+ return stub;
244
+ };
245
+ stub.once = (impl) => {
246
+ target._stubOnce(name, impl);
247
+ return stub;
248
+ };
249
+ stub.reset = () => {
250
+ target._stubReset(name);
251
+ return stub;
252
+ };
253
+ Object.defineProperty(stub, 'calls', { get: () => target._stubCalls(name), enumerable: false });
254
+ return stub;
255
+ }
256
+ /** Marker set by {@link mock} so {@link makeTestPort} can verify the class was decorated. */
257
+ const MOCK_MARKER = Symbol('ihsm.mock');
258
+ /**
259
+ * Class decorator that turns an **abstract** {@link TestPort} subclass into a preloadable mock.
260
+ *
261
+ * Declare each port method as an `abstract` member whose **signature matches the real port**, and
262
+ * decorate the class with `@`{@link mock}. Instances (built with {@link makeTestPort}) then expose
263
+ * every abstract method as a scriptable {@link Stubbed} method: it records each call and returns
264
+ * whatever the test scripted with `method.default(...)` / `method.once(...)`. You never write a
265
+ * method body — the behavior lives in the test, so one mock serves many scenarios.
266
+ *
267
+ * Concrete members (public fields holding device state, helper methods) are left untouched; only the
268
+ * abstract port methods are auto-stubbed.
269
+ *
270
+ * @example
271
+ * ```ts
272
+ * @ihsmTest.mock
273
+ * abstract class WatcherMock extends ihsmTest.TestPort<WatcherTop> {
274
+ * abstract watch(path: string): ihsm.ResultWithSubscription<number>; // signature matches the port
275
+ * }
276
+ *
277
+ * const port = ihsmTest.makeTestPort(WatcherMock);
278
+ * port.watch.default(path => ({ value: 1, subscription: { dispose: () => port.record('dispose') } }));
279
+ * ```
280
+ *
281
+ * @category Testing
282
+ */
283
+ export function mock(Ctor) {
284
+ const Decorated = class extends Ctor {
285
+ constructor(...args) {
286
+ super(...args);
287
+ const stubs = new Map();
288
+ const proxy = new Proxy(this, {
289
+ get(t, prop, receiver) {
290
+ if (typeof prop === 'string' && !(prop in t) && !NON_STUB_PROPS.has(prop)) {
291
+ let stub = stubs.get(prop);
292
+ if (stub === undefined) {
293
+ stub = buildMethodStub(t, prop);
294
+ stubs.set(prop, stub);
295
+ }
296
+ return stub;
297
+ }
298
+ return Reflect.get(t, prop, receiver);
299
+ },
300
+ });
301
+ return proxy;
302
+ }
303
+ };
304
+ Decorated[MOCK_MARKER] = true;
305
+ return Decorated;
306
+ }
307
+ /**
308
+ * Instantiate an `@`{@link mock}-decorated mock class — the canonical way to build a test port.
309
+ *
310
+ * Pass the mock **class**; you get back a typed instance whose abstract port methods (inferred from
311
+ * the machine's {@link TopState}) are scriptable {@link Stubbed} methods, ready for
312
+ * `port.method.default(...)`. The port's `actor` is still bound lazily when you hand the instance to
313
+ * {@link makeActor} / {@link makeTestActor}.
314
+ *
315
+ * @typeParam P - The mock class instance type (a {@link TestPort} subclass)
316
+ * @param PortClass - The `@mock`-decorated mock class
317
+ * @returns A scriptable {@link Mock} instance
318
+ * @throws If `PortClass` was not decorated with `@`{@link mock}
319
+ *
320
+ * @example
321
+ * ```ts
322
+ * const port = ihsmTest.makeTestPort(WatcherMock);
323
+ * port.watch.default(() => ({ value: 1, subscription: { dispose: () => port.send('onClosed') } }));
324
+ * const sm = ihsmTest.makeTestActor(WatcherTop, new WatcherCtx(), port);
325
+ * ```
326
+ *
327
+ * @category Testing
328
+ */
329
+ export function makeTestPort(PortClass) {
330
+ if (PortClass[MOCK_MARKER] !== true) {
331
+ throw new Error('ihsm: makeTestPort requires a class decorated with @ihsm.mock');
332
+ }
333
+ return new PortClass();
334
+ }
335
+ /**
336
+ * Creates a **full-access** actor for deterministic tests: merged protocol + typed `port`.
337
+ *
338
+ * Identical construction to {@link makeActor} (same three mandatory arguments + {@link ActorOptions}),
339
+ * but the returned {@link TestActor} exposes the merged {@link Dispatch} protocol — so tests can
340
+ * drive internal events directly (no live port required) — and grants typed access to `port` for
341
+ * asserting outbound interactions or pushing observations.
342
+ *
343
+ * Unlike {@link makeActor}, `traceLevel` defaults to {@link TraceLevel.VERBOSE_DEBUG} so a failing
344
+ * test is fully readable; opt down explicitly via `options.traceLevel` only when you need a quiet run.
345
+ *
346
+ * @typeParam Context - Domain context type
347
+ * @typeParam Public - Public protocol
348
+ * @typeParam Internal - Internal protocol
349
+ * @typeParam P - Port type
350
+ * @param topState - Root state class; `Context` / `Public` / `Internal` are inferred from it (see {@link TopStateArg})
351
+ * @param ctx - Mutable domain object shared by all states
352
+ * @param port - Outbound {@link Port} instance (its `actor` is bound by the factory)
353
+ * @param options - Optional tuning: `initialize` / `traceLevel` / `traceWriter` / … (see {@link ActorOptions})
354
+ * @returns A {@link TestActor} handle with full event + port access
355
+ *
356
+ * @example
357
+ * ```ts
358
+ * const sm = makeTestActor(ConnTop, new ConnCtx(), ihsmTest.makeTestPort(ConnMock));
359
+ * ```
360
+ *
361
+ * @category Factory
362
+ */
363
+ export function makeTestActor(topState, ctx, port, options = {}, ..._disjointGuard) {
364
+ // Tests default to the most verbose trace (so a failing run is fully readable). Never silence to
365
+ // a production level here — the user opts down explicitly via `options.traceLevel`.
366
+ const { initialize = defaultInitialize, traceLevel = TraceLevel.VERBOSE_DEBUG, traceWriter = defaultTraceWriter, dispatchErrorCallback = defaultDispatchErrorCallback } = options;
367
+ const hsm = makeHsm(topState, ctx, initialize, traceLevel, traceWriter, dispatchErrorCallback, port);
368
+ return hsm;
369
+ }
370
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/testing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "contributors": [
8
8
  "Roberto Boati"
9
9
  ],
10
- "description": "Class-based hierarchical state machines and actor mailboxes for TypeScript — typed post/call, zero dependencies",
10
+ "description": "Class-based hierarchical state machines and run-to-completion actors for TypeScript, designed for Deterministic Simulation Testing (DST) — typed post/call, zero dependencies",
11
11
  "files": [
12
12
  "lib"
13
13
  ],
@@ -40,7 +40,12 @@
40
40
  "fsm",
41
41
  "state machine",
42
42
  "hierarchical state machine",
43
- "statechart"
43
+ "statechart",
44
+ "deterministic simulation testing",
45
+ "dst",
46
+ "deterministic",
47
+ "testing",
48
+ "actor model"
44
49
  ],
45
50
  "license": "MIT",
46
51
  "maintainers": [
@@ -76,12 +81,23 @@
76
81
  "default": "./lib/cjs/index.js"
77
82
  }
78
83
  },
84
+ "./testing": {
85
+ "import": {
86
+ "types": "./lib/esm/testing.d.ts",
87
+ "default": "./lib/esm/testing.js"
88
+ },
89
+ "require": {
90
+ "types": "./lib/cjs/testing.d.ts",
91
+ "default": "./lib/cjs/testing.js"
92
+ }
93
+ },
79
94
  "./package.json": "./package.json"
80
95
  },
81
96
  "name": "ihsm",
82
97
  "repository": {
83
98
  "type": "git",
84
- "url": "https://github.com/filasieno/ihsm.git"
99
+ "url": "https://github.com/filasieno/ihsm.git",
100
+ "directory": "packages/ihsm"
85
101
  },
86
102
  "scripts": {
87
103
  "build-cjs": "tsc -b tsconfig.lib.json",
@@ -116,5 +132,5 @@
116
132
  "pretypecheck": "npm run prepare:ide"
117
133
  },
118
134
  "types": "./lib/cjs/index.d.ts",
119
- "version": "0.0.21"
135
+ "version": "0.0.22"
120
136
  }