obix-equivalence 0.2.1
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.
- package/README.md +42 -0
- package/dist/behavioural/index.d.ts +25 -0
- package/dist/behavioural/index.d.ts.map +1 -0
- package/dist/behavioural/index.js +54 -0
- package/dist/behavioural/index.js.map +1 -0
- package/dist/contracts/index.d.ts +34 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +42 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/equivalence/index.d.ts +23 -0
- package/dist/equivalence/index.d.ts.map +1 -0
- package/dist/equivalence/index.js +127 -0
- package/dist/equivalence/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/virtual-time/index.d.ts +14 -0
- package/dist/virtual-time/index.d.ts.map +1 -0
- package/dist/virtual-time/index.js +20 -0
- package/dist/virtual-time/index.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# obix-equivalence
|
|
2
|
+
|
|
3
|
+
**Adapter-equivalence orchestration + behavioural / contract DSL parsers.**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install obix-equivalence
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Equivalence (Problem 1)
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
const report = checkEquivalence(artifact, { trace: [["Start"],["Tick"],["Tick"],["Stop"]] });
|
|
13
|
+
report.expected; // oracle final state (from referenceFold — no adapters)
|
|
14
|
+
report.equivalent; // state + render + validation match, every step, every projection
|
|
15
|
+
report.stepWise; // states match at every step
|
|
16
|
+
report.renderEqual; // render() matches the oracle at every step
|
|
17
|
+
report.validationEqual; // validate() matches the oracle at every step
|
|
18
|
+
report.perAdapter; // data / functional / functional.create / oop / reactive traces
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The expected values are always `obix-validator.referenceFold`. Adapters are never
|
|
22
|
+
compared only to each other.
|
|
23
|
+
|
|
24
|
+
## Sub-modules (Problem 11 — one package, not two)
|
|
25
|
+
|
|
26
|
+
| Import | Contents |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `obix-equivalence` | everything |
|
|
29
|
+
| `.../equivalence` | `checkEquivalence` |
|
|
30
|
+
| `.../behavioural` | `parseTestDSL` (`Timer.test.obix`) |
|
|
31
|
+
| `.../contracts` | `parseContractDSL` (`Timer.obix.test`) |
|
|
32
|
+
| `.../virtual-time` | `runWithVirtualTime`, `createVirtualClock` |
|
|
33
|
+
|
|
34
|
+
## Dependency role
|
|
35
|
+
|
|
36
|
+
`obix-spec`, `obix-ir`, `obix-validator` + the four **pure** adapters (never the
|
|
37
|
+
native adapter). Adapters never depend on this package. Consumed by `obix-cli`.
|
|
38
|
+
|
|
39
|
+
## Level 0 status
|
|
40
|
+
|
|
41
|
+
✅ Equivalence orchestration + DSL parsing. Contract/behavioural *execution*
|
|
42
|
+
is driven by the CLI and consumers.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type BehaviouralStep = {
|
|
2
|
+
op: "dispatch";
|
|
3
|
+
action: string;
|
|
4
|
+
payload?: unknown;
|
|
5
|
+
} | {
|
|
6
|
+
op: "advance";
|
|
7
|
+
ms: number;
|
|
8
|
+
};
|
|
9
|
+
export interface Expectation {
|
|
10
|
+
target: string;
|
|
11
|
+
matcher: "is" | "isNot";
|
|
12
|
+
value: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface BehaviouralCase {
|
|
15
|
+
name: string;
|
|
16
|
+
givenProps?: Record<string, unknown>;
|
|
17
|
+
givenState?: Record<string, unknown>;
|
|
18
|
+
steps: BehaviouralStep[];
|
|
19
|
+
expectations: Expectation[];
|
|
20
|
+
}
|
|
21
|
+
export interface BehaviouralSuite {
|
|
22
|
+
cases: BehaviouralCase[];
|
|
23
|
+
}
|
|
24
|
+
export declare function parseTestDSL(source: string): BehaviouralSuite;
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/behavioural/index.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACrD;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAsBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAsB7D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const literal = (raw) => {
|
|
2
|
+
const t = raw.trim();
|
|
3
|
+
if (t === "true")
|
|
4
|
+
return true;
|
|
5
|
+
if (t === "false")
|
|
6
|
+
return false;
|
|
7
|
+
if (/^-?\d+(\.\d+)?$/.test(t))
|
|
8
|
+
return Number(t);
|
|
9
|
+
const s = t.match(/^"([^"]*)"$/);
|
|
10
|
+
if (s)
|
|
11
|
+
return s[1];
|
|
12
|
+
return t;
|
|
13
|
+
};
|
|
14
|
+
const objectLiteral = (raw) => {
|
|
15
|
+
const out = {};
|
|
16
|
+
const body = raw.trim().replace(/^\{/, "").replace(/\}$/, "");
|
|
17
|
+
for (const pair of body.split(",")) {
|
|
18
|
+
const m = pair.match(/^\s*([A-Za-z_$][\w$]*)\s*:\s*(.+?)\s*$/);
|
|
19
|
+
if (m)
|
|
20
|
+
out[m[1]] = literal(m[2]);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
};
|
|
24
|
+
export function parseTestDSL(source) {
|
|
25
|
+
const cases = [];
|
|
26
|
+
const re = /test\s+([A-Za-z_$][\w$]*)\s*\{([\s\S]*?)\n\}/g;
|
|
27
|
+
let m;
|
|
28
|
+
while ((m = re.exec(source)) !== null) {
|
|
29
|
+
const name = m[1];
|
|
30
|
+
const body = m[2];
|
|
31
|
+
const c = { name, steps: [], expectations: [] };
|
|
32
|
+
for (const lineRaw of body.split("\n")) {
|
|
33
|
+
const line = lineRaw.trim();
|
|
34
|
+
if (!line || line.startsWith("//"))
|
|
35
|
+
continue;
|
|
36
|
+
let g;
|
|
37
|
+
if ((g = line.match(/^given props\s+(\{.*\})$/)))
|
|
38
|
+
c.givenProps = objectLiteral(g[1]);
|
|
39
|
+
else if ((g = line.match(/^given state\s+(\{.*\})$/)))
|
|
40
|
+
c.givenState = objectLiteral(g[1]);
|
|
41
|
+
else if ((g = line.match(/^dispatch\s+([A-Za-z_$][\w$]*)(?:\s+(.+))?$/)))
|
|
42
|
+
c.steps.push({ op: "dispatch", action: g[1], payload: g[2] ? literal(g[2]) : undefined });
|
|
43
|
+
else if ((g = line.match(/^advance\s+(\d+)ms$/)))
|
|
44
|
+
c.steps.push({ op: "advance", ms: Number(g[1]) });
|
|
45
|
+
else if ((g = line.match(/^expect\s+(.+?)\s+is\s+not\s+(.+)$/)))
|
|
46
|
+
c.expectations.push({ target: g[1], matcher: "isNot", value: literal(g[2]) });
|
|
47
|
+
else if ((g = line.match(/^expect\s+(.+?)\s+is\s+(.+)$/)))
|
|
48
|
+
c.expectations.push({ target: g[1], matcher: "is", value: literal(g[2]) });
|
|
49
|
+
}
|
|
50
|
+
cases.push(c);
|
|
51
|
+
}
|
|
52
|
+
return { cases };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/behavioural/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface ContractActionDecl {
|
|
2
|
+
name: string;
|
|
3
|
+
arity: number;
|
|
4
|
+
readsProps: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface ContractDerivedDecl {
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ContractEffectDecl {
|
|
11
|
+
name: string;
|
|
12
|
+
every: number;
|
|
13
|
+
dispatches: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ContractInvariant {
|
|
16
|
+
name: string;
|
|
17
|
+
body: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ContractElement {
|
|
20
|
+
name: string;
|
|
21
|
+
body: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ContractModel {
|
|
24
|
+
dop: {
|
|
25
|
+
actions: ContractActionDecl[];
|
|
26
|
+
derived: ContractDerivedDecl[];
|
|
27
|
+
effects: ContractEffectDecl[];
|
|
28
|
+
};
|
|
29
|
+
invariants: ContractInvariant[];
|
|
30
|
+
elements: ContractElement[];
|
|
31
|
+
announce?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function parseContractDSL(source: string): ContractModel;
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AACD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE;QACH,OAAO,EAAE,kBAAkB,EAAE,CAAC;QAC9B,OAAO,EAAE,mBAAmB,EAAE,CAAC;QAC/B,OAAO,EAAE,kBAAkB,EAAE,CAAC;KAC/B,CAAC;IACF,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA0C9D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function parseContractDSL(source) {
|
|
2
|
+
const model = {
|
|
3
|
+
dop: { actions: [], derived: [], effects: [] },
|
|
4
|
+
invariants: [],
|
|
5
|
+
elements: [],
|
|
6
|
+
};
|
|
7
|
+
const dopBlock = source.match(/dop\s*\{([\s\S]*?)\n\}/);
|
|
8
|
+
if (dopBlock) {
|
|
9
|
+
for (const lineRaw of dopBlock[1].split("\n")) {
|
|
10
|
+
const line = lineRaw.trim();
|
|
11
|
+
let m;
|
|
12
|
+
if ((m = line.match(/^action\s+([A-Za-z_$][\w$]*)\s+arity\s+(\d+)\s+reads\s+props\s+\[([^\]]*)\]$/))) {
|
|
13
|
+
model.dop.actions.push({
|
|
14
|
+
name: m[1],
|
|
15
|
+
arity: Number(m[2]),
|
|
16
|
+
readsProps: m[3].split(",").map((s) => s.trim()).filter(Boolean),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
else if ((m = line.match(/^derived\s+([A-Za-z_$][\w$]*)\s*:\s*(\w+)$/))) {
|
|
20
|
+
model.dop.derived.push({ name: m[1], type: m[2] });
|
|
21
|
+
}
|
|
22
|
+
else if ((m = line.match(/^effect\s+([A-Za-z_$][\w$]*)\s+every\s+(\d+)\s+dispatches\s+([A-Za-z_$][\w$]*)$/))) {
|
|
23
|
+
model.dop.effects.push({ name: m[1], every: Number(m[2]), dispatches: m[3] });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const invRe = /invariant\s+([A-Za-z_$][\w$]*)\s*\{([\s\S]*?)\n\}/g;
|
|
28
|
+
let im;
|
|
29
|
+
while ((im = invRe.exec(source)) !== null) {
|
|
30
|
+
model.invariants.push({ name: im[1], body: im[2].trim() });
|
|
31
|
+
}
|
|
32
|
+
const elRe = /element\s+([A-Za-z_$][\w$]*)\s*\{([\s\S]*?)\n\}/g;
|
|
33
|
+
let em;
|
|
34
|
+
while ((em = elRe.exec(source)) !== null) {
|
|
35
|
+
model.elements.push({ name: em[1], body: em[2].trim() });
|
|
36
|
+
}
|
|
37
|
+
const ann = source.match(/announce\s*\{([\s\S]*?)\n\}/);
|
|
38
|
+
if (ann)
|
|
39
|
+
model.announce = ann[1].trim();
|
|
40
|
+
return model;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DOPArtifact, State, Props, ActionTrace, ValidationResult } from "obix-spec";
|
|
2
|
+
export interface EquivalenceScenario<S extends object, P extends object> {
|
|
3
|
+
trace: ActionTrace;
|
|
4
|
+
initialState?: S;
|
|
5
|
+
props?: P;
|
|
6
|
+
}
|
|
7
|
+
export interface AdapterRun<S extends object> {
|
|
8
|
+
states: S[];
|
|
9
|
+
renders: (string | undefined)[];
|
|
10
|
+
validations: (ValidationResult | undefined)[];
|
|
11
|
+
}
|
|
12
|
+
export interface EquivalenceReport<S extends object> {
|
|
13
|
+
equivalent: boolean;
|
|
14
|
+
stepWise: boolean;
|
|
15
|
+
renderEqual: boolean;
|
|
16
|
+
validationEqual: boolean;
|
|
17
|
+
expected: S;
|
|
18
|
+
oracleHistory: S[];
|
|
19
|
+
perAdapter: Record<string, AdapterRun<S>>;
|
|
20
|
+
divergences: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function checkEquivalence<S extends object = State, P extends object = Props>(artifact: DOPArtifact<S, P>, scenario: EquivalenceScenario<S, P>): EquivalenceReport<S>;
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/equivalence/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,WAAW,EACX,KAAK,EACL,KAAK,EACL,WAAW,EACX,gBAAgB,EACjB,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM;IACrE,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,CAAC;CACX;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM;IAC1C,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAChC,WAAW,EAAE,CAAC,gBAAgB,GAAG,SAAS,CAAC,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,MAAM;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,CAAC,CAAC;IACZ,aAAa,EAAE,CAAC,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAWD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAAE,CAAC,SAAS,MAAM,GAAG,KAAK,EACjF,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,QAAQ,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAClC,iBAAiB,CAAC,CAAC,CAAC,CA+CtB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { referenceFold } from "obix-validator";
|
|
2
|
+
import { toData, dataRender, dataValidate } from "obix-adapter-data";
|
|
3
|
+
import { toFunctional } from "obix-adapter-func";
|
|
4
|
+
import { toOOP } from "obix-adapter-oop";
|
|
5
|
+
import { toReactive } from "obix-adapter-reactive";
|
|
6
|
+
const stable = (v) => JSON.stringify(v, (_k, val) => val && typeof val === "object" && !Array.isArray(val)
|
|
7
|
+
? Object.fromEntries(Object.keys(val).sort().map((k) => [k, val[k]]))
|
|
8
|
+
: val);
|
|
9
|
+
const eq = (a, b) => stable(a) === stable(b);
|
|
10
|
+
export function checkEquivalence(artifact, scenario) {
|
|
11
|
+
const initialState = (scenario.initialState ?? artifact.initialState);
|
|
12
|
+
const props = (scenario.props ?? artifact.props);
|
|
13
|
+
const { trace } = scenario;
|
|
14
|
+
const oracle = referenceFold(artifact, initialState, props, trace);
|
|
15
|
+
const perAdapter = {
|
|
16
|
+
data: runData(artifact, initialState, props, trace),
|
|
17
|
+
functional: runFunctionalReduce(artifact, initialState, props, trace),
|
|
18
|
+
"functional.create": runFunctionalCreate(artifact, initialState, props, trace),
|
|
19
|
+
oop: runOOP(artifact, initialState, props, trace),
|
|
20
|
+
reactive: runReactive(artifact, initialState, props, trace),
|
|
21
|
+
};
|
|
22
|
+
const divergences = [];
|
|
23
|
+
let stepWise = true;
|
|
24
|
+
let renderEqual = true;
|
|
25
|
+
let validationEqual = true;
|
|
26
|
+
for (const [name, run] of Object.entries(perAdapter)) {
|
|
27
|
+
for (let i = 0; i < oracle.history.length; i++) {
|
|
28
|
+
if (!eq(run.states[i], oracle.history[i])) {
|
|
29
|
+
stepWise = false;
|
|
30
|
+
divergences.push(`${name} state@${i}: ${stable(run.states[i])} != ${stable(oracle.history[i])}`);
|
|
31
|
+
}
|
|
32
|
+
if (run.renders[i] !== undefined && oracle.renders[i] !== undefined && run.renders[i] !== oracle.renders[i]) {
|
|
33
|
+
renderEqual = false;
|
|
34
|
+
divergences.push(`${name} render@${i} differs from oracle`);
|
|
35
|
+
}
|
|
36
|
+
if (run.validations[i] !== undefined && oracle.validations[i] !== undefined && !eq(run.validations[i], oracle.validations[i])) {
|
|
37
|
+
validationEqual = false;
|
|
38
|
+
divergences.push(`${name} validation@${i} differs from oracle`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
equivalent: stepWise && renderEqual && validationEqual,
|
|
44
|
+
stepWise,
|
|
45
|
+
renderEqual,
|
|
46
|
+
validationEqual,
|
|
47
|
+
expected: oracle.finalState,
|
|
48
|
+
oracleHistory: oracle.history,
|
|
49
|
+
perAdapter,
|
|
50
|
+
divergences,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function renderAt(a, s, p) {
|
|
54
|
+
return a.render ? a.render(s, p) : undefined;
|
|
55
|
+
}
|
|
56
|
+
function validateAt(a, s, p) {
|
|
57
|
+
return a.validate ? a.validate(s, p) : undefined;
|
|
58
|
+
}
|
|
59
|
+
function runData(a, from, props, trace) {
|
|
60
|
+
const d = toData(a);
|
|
61
|
+
let s = from;
|
|
62
|
+
const states = [s];
|
|
63
|
+
const renders = [d.render ? dataRender(d, s, props) : undefined];
|
|
64
|
+
const validations = [d.validate ? dataValidate(d, s, props) : undefined];
|
|
65
|
+
for (const [name, payload] of trace) {
|
|
66
|
+
s = d.actions[name](s, payload, props);
|
|
67
|
+
states.push(s);
|
|
68
|
+
renders.push(d.render ? dataRender(d, s, props) : undefined);
|
|
69
|
+
validations.push(d.validate ? dataValidate(d, s, props) : undefined);
|
|
70
|
+
}
|
|
71
|
+
return { states, renders, validations };
|
|
72
|
+
}
|
|
73
|
+
function runFunctionalReduce(a, from, props, trace) {
|
|
74
|
+
const F = toFunctional(a);
|
|
75
|
+
let s = from;
|
|
76
|
+
const states = [s];
|
|
77
|
+
const renders = [renderAt(a, s, props)];
|
|
78
|
+
const validations = [validateAt(a, s, props)];
|
|
79
|
+
for (const [name, payload] of trace) {
|
|
80
|
+
s = F.reduce(s, name, payload, props);
|
|
81
|
+
states.push(s);
|
|
82
|
+
renders.push(renderAt(a, s, props));
|
|
83
|
+
validations.push(validateAt(a, s, props));
|
|
84
|
+
}
|
|
85
|
+
return { states, renders, validations };
|
|
86
|
+
}
|
|
87
|
+
function runFunctionalCreate(a, from, props, trace) {
|
|
88
|
+
const inst = toFunctional(a).create({ state: from, props });
|
|
89
|
+
const states = [inst.getState()];
|
|
90
|
+
const renders = [a.render ? inst.render() : undefined];
|
|
91
|
+
const validations = [a.validate ? inst.validate() : undefined];
|
|
92
|
+
for (const [name, payload] of trace) {
|
|
93
|
+
inst.dispatch(name, payload);
|
|
94
|
+
states.push(inst.getState());
|
|
95
|
+
renders.push(a.render ? inst.render() : undefined);
|
|
96
|
+
validations.push(a.validate ? inst.validate() : undefined);
|
|
97
|
+
}
|
|
98
|
+
return { states, renders, validations };
|
|
99
|
+
}
|
|
100
|
+
function runOOP(a, from, props, trace) {
|
|
101
|
+
const Ctor = toOOP(a);
|
|
102
|
+
const inst = new Ctor({ state: from, props });
|
|
103
|
+
const states = [inst.state];
|
|
104
|
+
const renders = [a.render ? inst.render() : undefined];
|
|
105
|
+
const validations = [a.validate ? inst.validate() : undefined];
|
|
106
|
+
for (const [name, payload] of trace) {
|
|
107
|
+
inst.dispatch(name, payload);
|
|
108
|
+
states.push(inst.state);
|
|
109
|
+
renders.push(a.render ? inst.render() : undefined);
|
|
110
|
+
validations.push(a.validate ? inst.validate() : undefined);
|
|
111
|
+
}
|
|
112
|
+
return { states, renders, validations };
|
|
113
|
+
}
|
|
114
|
+
function runReactive(a, from, props, trace) {
|
|
115
|
+
const inst = toReactive(a)({ state: from, props });
|
|
116
|
+
const states = [inst.state];
|
|
117
|
+
const renders = [a.render ? inst.render() : undefined];
|
|
118
|
+
const validations = [a.validate ? inst.validate() : undefined];
|
|
119
|
+
for (const [name, payload] of trace) {
|
|
120
|
+
inst.dispatch(name, payload);
|
|
121
|
+
states.push(inst.state);
|
|
122
|
+
renders.push(a.render ? inst.render() : undefined);
|
|
123
|
+
validations.push(a.validate ? inst.validate() : undefined);
|
|
124
|
+
}
|
|
125
|
+
return { states, renders, validations };
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/equivalence/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { checkEquivalence, type EquivalenceScenario, type EquivalenceReport, type AdapterRun, } from "./equivalence/index.js";
|
|
2
|
+
export { parseTestDSL, type BehaviouralSuite, type BehaviouralCase, type BehaviouralStep, type Expectation, } from "./behavioural/index.js";
|
|
3
|
+
export { parseContractDSL, type ContractModel, type ContractActionDecl, type ContractDerivedDecl, type ContractEffectDecl, type ContractInvariant, type ContractElement, } from "./contracts/index.js";
|
|
4
|
+
export { runWithVirtualTime, createVirtualClock, type VirtualRun, } from "./virtual-time/index.js";
|
|
5
|
+
export { referenceFold } from "obix-validator";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,UAAU,GAChB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,UAAU,GAChB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { checkEquivalence, } from "./equivalence/index.js";
|
|
2
|
+
export { parseTestDSL, } from "./behavioural/index.js";
|
|
3
|
+
export { parseContractDSL, } from "./contracts/index.js";
|
|
4
|
+
export { runWithVirtualTime, createVirtualClock, } from "./virtual-time/index.js";
|
|
5
|
+
export { referenceFold } from "obix-validator";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gBAAgB,GAIjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,YAAY,GAKb,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,gBAAgB,GAOjB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DOPArtifact, State, Props } from "obix-spec";
|
|
2
|
+
export { createVirtualClock } from "obix-effects";
|
|
3
|
+
export interface VirtualRun<S extends object, P extends object> {
|
|
4
|
+
readonly state: S;
|
|
5
|
+
readonly transitions: number;
|
|
6
|
+
dispatch(action: string, payload?: unknown): void;
|
|
7
|
+
advance(ms: number): void;
|
|
8
|
+
stop(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function runWithVirtualTime<S extends object = State, P extends object = Props>(artifact: DOPArtifact<S, P>, opts?: {
|
|
11
|
+
state?: S;
|
|
12
|
+
props?: Partial<P>;
|
|
13
|
+
}): VirtualRun<S, P>;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/virtual-time/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM;IAC5D,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;CACd;AAOD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAAE,CAAC,SAAS,MAAM,GAAG,KAAK,EACnF,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CAAO,GAC3C,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAelB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createVirtualClock } from "obix-effects";
|
|
2
|
+
import { toReactive } from "obix-adapter-reactive";
|
|
3
|
+
export { createVirtualClock } from "obix-effects";
|
|
4
|
+
export function runWithVirtualTime(artifact, opts = {}) {
|
|
5
|
+
const vc = createVirtualClock();
|
|
6
|
+
const inst = toReactive(artifact)(opts);
|
|
7
|
+
inst.startEffects(vc.clock);
|
|
8
|
+
return {
|
|
9
|
+
get state() {
|
|
10
|
+
return inst.state;
|
|
11
|
+
},
|
|
12
|
+
get transitions() {
|
|
13
|
+
return inst.transitions;
|
|
14
|
+
},
|
|
15
|
+
dispatch: (action, payload) => void inst.dispatch(action, payload),
|
|
16
|
+
advance: (ms) => vc.advance(ms),
|
|
17
|
+
stop: () => inst.stopEffects(),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/virtual-time/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAelD,MAAM,UAAU,kBAAkB,CAChC,QAA2B,EAC3B,OAA0C,EAAE;IAE5C,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO;QACL,IAAI,KAAK;YACP,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,CAAC;QACD,IAAI,WAAW;YACb,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QAClE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE;KAC/B,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "obix-equivalence",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "OBIX adapter-equivalence orchestration + behavioural/contract DSL parsers. Compares every projection to the INDEPENDENT obix-validator.referenceFold oracle, step by step. Depends on spec, ir, validator and the four pure adapters.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./equivalence": {
|
|
17
|
+
"types": "./dist/equivalence/index.d.ts",
|
|
18
|
+
"import": "./dist/equivalence/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./behavioural": {
|
|
21
|
+
"types": "./dist/behavioural/index.d.ts",
|
|
22
|
+
"import": "./dist/behavioural/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./contracts": {
|
|
25
|
+
"types": "./dist/contracts/index.d.ts",
|
|
26
|
+
"import": "./dist/contracts/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./virtual-time": {
|
|
29
|
+
"types": "./dist/virtual-time/index.d.ts",
|
|
30
|
+
"import": "./dist/virtual-time/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
},
|
|
34
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -p tsconfig.json"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"obix-spec": "0.2.1",
|
|
40
|
+
"obix-ir": "0.2.1",
|
|
41
|
+
"obix-validator": "0.2.1",
|
|
42
|
+
"obix-adapter-data": "0.2.1",
|
|
43
|
+
"obix-adapter-func": "0.2.1",
|
|
44
|
+
"obix-adapter-oop": "0.2.1",
|
|
45
|
+
"obix-adapter-reactive": "0.2.1"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.11.0"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/obinexusmk2/obix-monorepo-2026.git",
|
|
56
|
+
"directory": "packages/obix-equivalence"
|
|
57
|
+
}
|
|
58
|
+
}
|