@agoric/internal 0.3.3-dev-cbcea8c.0.cbcea8c → 0.3.3-dev-04baeed.0.04baeed

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/internal",
3
- "version": "0.3.3-dev-cbcea8c.0.cbcea8c",
3
+ "version": "0.3.3-dev-04baeed.0.04baeed",
4
4
  "description": "Externally unsupported utilities internal to agoric-sdk",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "lint:types": "yarn run -T tsgo --tsBuildInfoFile tsconfig.tsgo.tsbuildinfo"
25
25
  },
26
26
  "dependencies": {
27
- "@agoric/base-zone": "0.1.1-dev-cbcea8c.0.cbcea8c",
27
+ "@agoric/base-zone": "0.1.1-dev-04baeed.0.04baeed",
28
28
  "@endo/cache-map": "^1.1.0",
29
29
  "@endo/common": "^1.4.0",
30
30
  "@endo/compartment-mapper": "^2.3.0",
@@ -42,7 +42,7 @@
42
42
  "jessie.js": "^0.3.4"
43
43
  },
44
44
  "devDependencies": {
45
- "@agoric/cosmic-proto": "0.4.1-dev-cbcea8c.0.cbcea8c",
45
+ "@agoric/cosmic-proto": "0.4.1-dev-04baeed.0.04baeed",
46
46
  "@endo/exo": "^1.7.0",
47
47
  "@endo/init": "^1.1.13",
48
48
  "@endo/ses-ava": "^1.4.2",
@@ -70,5 +70,5 @@
70
70
  "typeCoverage": {
71
71
  "atLeast": 92.84
72
72
  },
73
- "gitHead": "cbcea8c2415f2c9c4bc1ea9ff90730f2773bafaa"
73
+ "gitHead": "04baeedd0adc9b2480dd9d272e8daffebc408662"
74
74
  }
@@ -14,7 +14,10 @@
14
14
  */
15
15
  export const eventLoopIteration: () => Promise<void>;
16
16
  export function inspectMapStore(store: MapStore): object;
17
- export function testInterruptedSteps<Input = any, Context = unknown>(t: AvaT<Context>, allSteps: readonly TestStep<Input>[], doInterrupt?: (t: AvaT<Context>) => ERef<void>): Promise<void>;
17
+ export function testInterruptedSteps<Input = any, Context = unknown>(t: AvaT<Context>, allSteps: readonly TestStep<Input>[], doInterrupt?: (t: AvaT<Context>) => ERef<void>, { setup, postcondition }?: {
18
+ setup?: ((t: AvaT<Context>) => Partial<Input> | PromiseLike<Partial<Input>>) | undefined;
19
+ postcondition?: ((t: AvaT<Context>, accum: Partial<Input>, label: string) => ERef<void>) | undefined;
20
+ }): Promise<void>;
18
21
  export type TestStep<Input = any> = readonly [stepName: string, fn: (input: Partial<Input>, label: string) => Partial<Input> | PromiseLike<Partial<Input>>];
19
22
  import type { MapStore } from '@agoric/store';
20
23
  import type { ExecutionContext as AvaT } from 'ava';
@@ -1 +1 @@
1
- {"version":3,"file":"testing-utils.d.ts","sourceRoot":"","sources":["testing-utils.js"],"names":[],"mappings":"AACA;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,iCAFU,MAAM,OAAO,CAAC,IAAI,CAAC,CAGmB;AAgBzC,uCAHI,QAAQ,GACN,MAAM,CAsBlB;AAqBM,qCANO,KAAK,QACL,OAAO,eACV,KAAK,OAAO,CAAC,YACb,SAAS,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAC1B,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,iBA8D1C;qBA7Ea,KAAK,UACN,SAAS,CACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAC3F;8BA3DuB,eAAe;8CACC,KAAK;0BACzB,qBAAqB"}
1
+ {"version":3,"file":"testing-utils.d.ts","sourceRoot":"","sources":["testing-utils.js"],"names":[],"mappings":"AACA;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,iCAFU,MAAM,OAAO,CAAC,IAAI,CAAC,CAGmB;AAgBzC,uCAHI,QAAQ,GACN,MAAM,CAsBlB;AAwCM,qCAjBO,KAAK,QACL,OAAO,eACV,KAAK,OAAO,CAAC,YACb,SAAS,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAC1B,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,6BAExC;IAAqF,KAAK,QAA9E,KAAK,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAMe,aAAa,QAA1F,KAAK,OAAO,CAAC,SAAS,OAAO,CAAC,KAAK,CAAC,SAAS,MAAM,KAAK,KAAK,IAAI,CAAC;CAIhF,iBAoFA;qBAvHa,KAAK,UACN,SAAS,CACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAC3F;8BA3DuB,eAAe;8CACC,KAAK;0BACzB,qBAAqB"}
@@ -66,13 +66,37 @@ harden(inspectMapStore);
66
66
  * For each step, run to just before that point and pause for continuation after
67
67
  * interrupt.
68
68
  *
69
+ * `allSteps` should contain only steps that are meaningful interruption
70
+ * boundaries — i.e. that leave durable in-flight state whose recovery across an
71
+ * interrupt is worth asserting. Each step in `allSteps` runs `allSteps.length +
72
+ * 2` times, so the total work is quadratic in the number of steps; keep the
73
+ * list to the genuinely mutating steps. Use `options.setup` for non-mutating
74
+ * fixtures and `options.postcondition` for non-mutating outcome assertions so
75
+ * they don't inflate the boundary count.
76
+ *
69
77
  * @template [Input=any]
70
78
  * @template [Context=unknown]
71
79
  * @param {AvaT<Context>} t
72
80
  * @param {readonly TestStep<Input>[]} allSteps
73
81
  * @param {(t: AvaT<Context>) => ERef<void>} [doInterrupt]
82
+ * @param {object} [options]
83
+ * @param {(t: AvaT<Context>) => Partial<Input> | PromiseLike<Partial<Input>>} [options.setup]
84
+ * Produce the initial accumulator at the start of each run. Runs are never
85
+ * interrupted around setup, so use it for fixtures (e.g. funding a wallet)
86
+ * that are not themselves part of the interruption-resilience contract. It is
87
+ * invoked once per run, so it may create per-run state (e.g. a single-use
88
+ * actor) safely.
89
+ * @param {(t: AvaT<Context>, accum: Partial<Input>, label: string) => ERef<void>} [options.postcondition]
90
+ * Assert the outcome after each run that completes all of its steps (the
91
+ * pre-interrupt run, the post-interrupt run, and each resumed run). Use for
92
+ * non-mutating outcome checks that need not be interruption boundaries.
74
93
  */
75
- export const testInterruptedSteps = async (t, allSteps, doInterrupt) => {
94
+ export const testInterruptedSteps = async (
95
+ t,
96
+ allSteps,
97
+ doInterrupt,
98
+ { setup, postcondition } = {},
99
+ ) => {
76
100
  /**
77
101
  * @typedef {{
78
102
  * label: string;
@@ -80,16 +104,20 @@ export const testInterruptedSteps = async (t, allSteps, doInterrupt) => {
80
104
  * }} RunState
81
105
  */
82
106
 
107
+ /** @returns {Promise<Partial<Input>>} */
108
+ const freshAccum = async () => (setup ? setup(t) : {});
109
+
83
110
  /**
84
111
  * @param {string} label
85
112
  * @param {readonly TestStep<Input>[]} steps
86
- * @param {RunState} [runState]
113
+ * @param {RunState} [runState] when omitted, a fresh run is started, seeding
114
+ * the accumulator from `setup`.
87
115
  * @returns {Promise<RunState>}
88
116
  */
89
- const runSteps = async (label, steps, runState = { label, accum: {} }) => {
117
+ const runSteps = async (label, steps, runState) => {
90
118
  await null;
91
- let accum = runState.accum;
92
- const runLabel = runState.label;
119
+ let accum = runState ? runState.accum : await freshAccum();
120
+ const runLabel = runState ? runState.label : label;
93
121
  for (const [stepName, fn] of steps) {
94
122
  await t.notThrowsAsync(async () => {
95
123
  accum = await fn(accum, runLabel);
@@ -98,8 +126,20 @@ export const testInterruptedSteps = async (t, allSteps, doInterrupt) => {
98
126
  return { label: runLabel, accum };
99
127
  };
100
128
 
129
+ /**
130
+ * @param {RunState} runState
131
+ * @returns {Promise<RunState>}
132
+ */
133
+ const complete = async runState => {
134
+ await null;
135
+ if (postcondition) {
136
+ await postcondition(t, runState.accum, runState.label);
137
+ }
138
+ return runState;
139
+ };
140
+
101
141
  // Sanity check
102
- await runSteps('pre-interrupt', allSteps);
142
+ await complete(await runSteps('pre-interrupt', allSteps));
103
143
  if (!doInterrupt) {
104
144
  return;
105
145
  }
@@ -116,7 +156,7 @@ export const testInterruptedSteps = async (t, allSteps, doInterrupt) => {
116
156
  const runState = await runSteps(
117
157
  `pre-${beforeStepName}`,
118
158
  allSteps.slice(0, i),
119
- { label: `pause-before-${beforeStepName}`, accum: {} },
159
+ { label: `pause-before-${beforeStepName}`, accum: await freshAccum() },
120
160
  );
121
161
  pausedRuns.push({ runState, remainingSteps: allSteps.slice(i) });
122
162
  }
@@ -125,12 +165,14 @@ export const testInterruptedSteps = async (t, allSteps, doInterrupt) => {
125
165
  await doInterrupt(t);
126
166
 
127
167
  // Verify a complete run post-interrupt.
128
- await runSteps('post-interrupt', allSteps);
168
+ await complete(await runSteps('post-interrupt', allSteps));
129
169
 
130
170
  // Verify completion of each paused step.
131
171
  for (const { runState, remainingSteps } of pausedRuns) {
132
172
  const [beforeStepName] = remainingSteps[0];
133
- await runSteps(`resumed-${beforeStepName}`, remainingSteps, runState);
173
+ await complete(
174
+ await runSteps(`resumed-${beforeStepName}`, remainingSteps, runState),
175
+ );
134
176
  }
135
177
  };
136
178
  harden(testInterruptedSteps);