Skip to content

@aosengine/test-harness

Interfaces

FrameInputOverrides

Fields createFrameInput accepts.

Properties

bodies?
ts
optional bodies?: Float32Array<ArrayBufferLike>;

Packed body rows, stride 14.

contacts?
ts
optional contacts?: readonly Contact[];

Reported contacts.

dt?
ts
optional dt?: number;

Fixed timestep in seconds. Default 1 / 60.

elapsed?
ts
optional elapsed?: number;

Simulated seconds since init. Defaults to frame * dt.

events?
ts
optional events?: readonly GameEvent[];

Host-side events.

frame?
ts
optional frame?: number | bigint;

Fixed-step counter. Accepts a number for convenience.

input?
ts
optional input?: MutableInputState;

Input state to reuse; a fresh neutral one is built when absent.


LogLine

One recorded env.log call.

Properties

level
ts
level: LogLevel;
msg
ts
msg: string;

MockAsset

A manifest entry the mock host will resolve.

Properties

hasCollider?
ts
optional hasCollider?: boolean;

Whether a collider asset is attached. Default false.

kind?
ts
optional kind?: AssetKind;

Asset family. Default 'data'.

name
ts
name: string;

Manifest string id.

ready?
ts
optional ready?: boolean;

Whether the bytes are resident. Default true.

rig?
ts
optional rig?: string;

Rig backend for character assets.

tags?
ts
optional tags?: readonly string[];

Tags, verbatim.


MockHost

A mock host, plus the recordings a test asserts on.

Extends

Properties

log_
ts
readonly log_: LogLine[];

Every env.log call, in order.

rayCalls
ts
readonly rayCalls: object;

How many raycast calls the guest made.

batch
ts
batch: number;
overlap
ts
overlap: number;
raycast
ts
raycast: number;

Methods

describe()
ts
describe(id): AssetDesc | null | undefined;

Metadata for a handle, or nullish when the handle is unknown.

Parameters
ParameterType
idnumber
Returns

AssetDesc | null | undefined

Inherited from

HostApi.describe

handleOf()
ts
handleOf(name): number;

The handle a name resolves to, minting one when needed.

Parameters
ParameterType
namestring
Returns

number

log()
ts
log(level, msg): void;

Route a message to the host logger.

Parameters
ParameterType
levelLogLevel
msgstring
Returns

void

Inherited from

HostApi.log

nowMs()
ts
nowMs(): number;

Monotonic milliseconds since engine start. Never feed this to simulation.

Returns

number

Inherited from

HostApi.nowMs

overlapSphere()
ts
overlapSphere(
   center, 
   radius, 
   filter, 
   maxResults
): readonly OverlapHit[];

Bodies overlapping a sphere, nearest first.

Parameters
ParameterType
centerVec3
radiusnumber
filterQueryFilter
maxResultsnumber
Returns

readonly OverlapHit[]

Inherited from

HostApi.overlapSphere

raycast()
ts
raycast(
   origin, 
   direction, 
   maxDistance, 
   filter
): RayHit | null | undefined;

Closest hit along a ray, or nullish on a miss.

Parameters
ParameterType
originVec3
directionVec3
maxDistancenumber
filterQueryFilter
Returns

RayHit | null | undefined

Inherited from

HostApi.raycast

raycastBatch()
ts
raycastBatch(rays): readonly (RayHit | null | undefined)[];

One round trip for many rays; result index i matches rays[i].

Parameters
ParameterType
raysreadonly RayQuery[]
Returns

readonly (RayHit | null | undefined)[]

Inherited from

HostApi.raycastBatch

reset()
ts
reset(): void;

Forget every recording.

Returns

void

resolveId()
ts
resolveId(name): number | null | undefined;

Manifest string id to handle, or nullish when the manifest has no entry.

Parameters
ParameterType
namestring
Returns

number | null | undefined

Inherited from

HostApi.resolveId

seed()
ts
seed(): number;

The deterministic run seed, as a number (already Number()-coerced).

Returns

number

Inherited from

HostApi.seed

warnings()
ts
warnings(): LogLine[];

Lines at 'warn' or 'error'.

Returns

LogLine[]


MockHostOptions

How to build a mock host.

Properties

assets?
ts
optional assets?: readonly (string | MockAsset)[];

Manifest entries. Names not listed still resolve, to stable synthetic handles, so a test never has to enumerate a game's assets.

nowMs?
ts
optional nowMs?: () => number;

Milliseconds env.nowMs() returns; defaults to a 0.1 ms counter.

Returns

number

overlapSphere?
ts
optional overlapSphere?: (center, radius, filter, maxResults) => readonly OverlapHit[];

Scripted sphere overlap. Default: no hits.

Parameters
ParameterType
centerVec3
radiusnumber
filterQueryFilter
maxResultsnumber
Returns

readonly OverlapHit[]

raycast?
ts
optional raycast?: (origin, direction, maxDistance, filter) => RayHit | null;

Scripted raycast. Return null for a miss. Default: always a miss.

Parameters
ParameterType
originVec3
directionVec3
maxDistancenumber
filterQueryFilter
Returns

RayHit | null

seed?
ts
optional seed?: number;

The value env.seed() returns. Default 0x5eed1234.

strictAssets?
ts
optional strictAssets?: boolean;

Refuse to resolve names that are not in assets. Default false.


MutableInputState

A mutable, host-shaped input state.

Extends

Properties

focused
ts
focused: boolean;
Overrides

InputState.focused

gamepads
ts
gamepads: GamepadState[];
Overrides

InputState.gamepads

keys
ts
keys: object;
down
ts
down: Uint32Array;
pressed
ts
pressed: Uint32Array;
released
ts
released: Uint32Array;
Overrides

InputState.keys

mods
ts
mods: InputMods;
Overrides

InputState.mods

mouse
ts
mouse: MouseState;
Overrides

InputState.mouse


SimulateOptions

How to run a simulation.

Properties

dt?
ts
optional dt?: number;

Fixed timestep in seconds. Default 1 / 60.

frames
ts
frames: number;

How many frames to run.

keepOutputs?
ts
optional keepOutputs?: boolean;

Keep every frame-output. Off by default: outputs are reused objects.

script?
ts
optional script?: FrameScript;

Per-frame overrides. Mutate input (the same state object is reused and its edges cleared between frames) or return fields to merge.


SimulateResult

What a simulation produced.

Properties

commandTags
ts
commandTags: string[][];

Commands seen per frame, by tag.

hash
ts
hash: number;

Combined hash of every frame.

hashes
ts
hashes: number[];

One hashFrameOutput per frame, in order.

hud
ts
hud: object[];

Every HUD payload that crossed, with the frame it crossed on.

frame
ts
frame: number;
json
ts
json: string;
outputs
ts
outputs: FrameOutput[];

Outputs, when keepOutputs is set.

transformRows
ts
transformRows: number[];

Transform row counts per frame.


Tickable

Anything with the guest's per-frame entry point.

Methods

tick()
ts
tick(input): FrameOutput;
Parameters
ParameterType
inputHostFrameInput
Returns

FrameOutput

Type Aliases

FrameScript

ts
type FrameScript = (frame, input) => FrameInputOverrides | void;

A per-frame script. Mutate input in place, and optionally return fields to merge into the frame.

void in the return union is deliberate: a script that only mutates input should not have to write return undefined.

Parameters

ParameterType
framenumber
inputMutableInputState

Returns

FrameInputOverrides | void

Variables

PACKAGE

ts
const PACKAGE: "@aosengine/test-harness";

Package identity marker.

Example

ts
import { PACKAGE } from '@aosengine/test-harness';

console.log(PACKAGE); // '@aosengine/test-harness'

Functions

createFrameInput()

ts
function createFrameInput(overrides?): HostFrameInput;

Build one frame-input, in host-side shapes.

Parameters

ParameterTypeDescription
overridesFrameInputOverridesAnything to change from the neutral frame.

Returns

HostFrameInput

A fresh frame input.

Example

ts
import { createFrameInput } from '@aosengine/test-harness';

const input = createFrameInput({ frame: 0 });

createGameConfig()

ts
function createGameConfig(overrides?): HostGameConfig;

Build a game-config, in host-side shapes.

Parameters

ParameterTypeDescription
overridesPartial<HostGameConfig>Anything to change from the defaults.

Returns

HostGameConfig

A fresh config.

Example

ts
import { createGameConfig } from '@aosengine/test-harness';

sandbox.init(createGameConfig({ seed: 7n }));

createInputState()

ts
function createInputState(): MutableInputState;

Build a neutral input state: nothing held, nothing moving, canvas focused.

Returns

MutableInputState

A fresh mutable input state.

Example

ts
import { createInputState, press } from '@aosengine/test-harness';

const state = createInputState();
press(state, 'W');

createMockHost()

ts
function createMockHost(options?): MockHost;

Create a scripted host.

Parameters

ParameterTypeDescription
optionsMockHostOptionsSeed, scripted queries and the manifest.

Returns

MockHost

A HostApi with recordings attached.

Example

ts
import { createMockHost } from '@aosengine/test-harness';

const host = createMockHost({
  seed: 42,
  raycast: (origin) => ({
    body: 1,
    entity: 1,
    point: origin,
    normal: { x: 0, y: 1, z: 0 },
    distance: 2,
  }),
});

endFrame()

ts
function endFrame(state): void;

Clear the per-frame edges, keeping held keys held.

Call this between frames, exactly as @aosengine/input does.

Parameters

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.

Returns

void

Nothing.

Example

ts
import { endFrame } from '@aosengine/test-harness';

endFrame(state);

hashCommands()

ts
function hashCommands(commands): number;

Hash a command list.

Commands are JSON, not floats: their payloads are structural, and a textual difference is exactly what a parity test wants to see.

Parameters

ParameterTypeDescription
commandsreadonly Command[]The frame-output.commands list.

Returns

number

A 32-bit hash.

Example

ts
import { hashCommands } from '@aosengine/test-harness';

expect(hashCommands(out.commands)).toMatchInlineSnapshot();

hashFrameOutput()

ts
function hashFrameOutput(out): number;

Hash a whole frame-output: transforms, commands, camera and HUD.

Parameters

ParameterTypeDescription
outFrameOutputThe output to hash.

Returns

number

A 32-bit hash.

Example

ts
import { hashFrameOutput } from '@aosengine/test-harness';

expect(hashFrameOutput(direct)).toBe(hashFrameOutput(wasm));

hashString()

ts
function hashString(hash, text): number;

Fold a string into a running FNV-1a hash.

Parameters

ParameterTypeDescription
hashnumberThe running hash.
textstringThe string.

Returns

number

The new hash.


hashTransforms()

ts
function hashTransforms(transforms): number;

Hash a packed transform buffer.

Parameters

ParameterTypeDescription
transformsArrayLike<number>The frame-output.transforms list, stride 12.

Returns

number

A 32-bit hash.

Example

ts
import { hashTransforms } from '@aosengine/test-harness';

expect(hashTransforms(a.transforms)).toBe(hashTransforms(b.transforms));

hashU32()

ts
function hashU32(hash, word): number;

Fold a 32-bit word into a running FNV-1a hash, little-endian.

Parameters

ParameterTypeDescription
hashnumberThe running hash.
wordnumberThe word.

Returns

number

The new hash.


packBodies()

ts
function packBodies(rows): Float32Array;

Build a packed bodies row set, stride 14.

Parameters

ParameterTypeDescription
rowsreadonly object[]One entry per live body.

Returns

Float32Array

A Float32Array sorted ascending by body id.

Example

ts
import { packBodies } from '@aosengine/test-harness';

const bodies = packBodies([{ body: 1, position: [0, 1, 0] }]);

press()

ts
function press(state, key): void;

Hold a key down and record the press edge.

Parameters

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
keystringA key name: 'KeyW', 'W', 'Shift'.

Returns

void

Nothing.

Example

ts
import { createInputState, press } from '@aosengine/test-harness';

const state = createInputState();
press(state, 'Space');

pressMouse()

ts
function pressMouse(state, button): void;

Press a mouse button.

Parameters

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
buttonnumberA bit mask; 1 left, 2 right, 4 middle.

Returns

void

Nothing.

Example

ts
import { pressMouse } from '@aosengine/test-harness';

pressMouse(state, 1);

release()

ts
function release(state, key): void;

Release a key and record the release edge.

Parameters

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
keystringA key name.

Returns

void

Nothing.

Example

ts
import { release } from '@aosengine/test-harness';

release(state, 'Space');

releaseMouse()

ts
function releaseMouse(state, button): void;

Release a mouse button.

Parameters

ParameterTypeDescription
stateMutableInputStateThe input state to mutate.
buttonnumberA bit mask.

Returns

void

Nothing.

Example

ts
import { releaseMouse } from '@aosengine/test-harness';

releaseMouse(state, 1);

simulate()

ts
function simulate(guest, options): SimulateResult;

Run a guest for frames fixed steps.

Parameters

ParameterTypeDescription
guestTickableAnything with a tick, including a Sandbox.
optionsSimulateOptionsFrame count and the per-frame script.

Returns

SimulateResult

Hashes, command tags, HUD payloads and row counts.

Example

ts
import { simulate, press } from '@aosengine/test-harness';

const result = simulate(sandbox, {
  frames: 300,
  script: (frame, input) => {
    if (frame === 10) press(input, 'W');
  },
});

stableJson()

ts
function stableJson(value): string;

JSON with object keys sorted, so two structurally identical payloads hash the same whatever order their fields were assigned in.

Parameters

ParameterTypeDescription
valueunknownAnything JSON-serialisable.

Returns

string

The canonical rendering.