Skip to content

Commit

Permalink
support for watchedPromises in fakeVirtualSupport (#8661)
Browse files Browse the repository at this point in the history
* test: support for watchedPromises in fakeVirtualSupport

Needed by #8488

* chore: update allocatePromiseID to use nextExportID

* chore: distinct ID range for proises
  • Loading branch information
Chris-Hibbert committed Jan 16, 2024
1 parent a1602da commit f31ccb0
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -587,12 +587,12 @@ test('durable kind IDs can be reanimated', t => {

// Store it in the store without having used it
placeToPutIt.init('savedKindID', kindHandle);
t.is(log.shift(), 'get vc.1.ssavedKindID => undefined');
t.is(log.shift(), 'get vc.4.ssavedKindID => undefined');
t.is(log.shift(), `get vom.rc.${khid} => undefined`);
t.is(log.shift(), `set vom.rc.${khid} 1`);
t.is(log.shift(), `set vc.1.ssavedKindID ${vstr(kind)}`);
t.is(log.shift(), 'get vc.1.|entryCount => 0');
t.is(log.shift(), 'set vc.1.|entryCount 1');
t.is(log.shift(), `set vc.4.ssavedKindID ${vstr(kind)}`);
t.is(log.shift(), 'get vc.4.|entryCount => 0');
t.is(log.shift(), 'set vc.4.|entryCount 1');
t.deepEqual(log, []);

// Forget its Representative
Expand All @@ -606,7 +606,7 @@ test('durable kind IDs can be reanimated', t => {

// Fetch it from the store, which should reanimate it
const fetchedKindID = placeToPutIt.get('savedKindID');
t.is(log.shift(), `get vc.1.ssavedKindID => ${vstr(kind)}`);
t.is(log.shift(), `get vc.4.ssavedKindID => ${vstr(kind)}`);
t.is(
log.shift(),
'get vom.dkind.10.descriptor => {"kindID":"10","tag":"testkind"}',
Expand Down Expand Up @@ -654,9 +654,23 @@ test('virtual object gc', t => {
];
t.is(log.shift(), `get storeKindIDTable => undefined`);
t.is(log.shift(), `set ${skit[0]} ${skit[1]}`);
t.is(log.shift(), 'set vc.1.|nextOrdinal 1');
t.is(log.shift(), 'set vc.1.|entryCount 0');
t.is(log.shift(), 'get watcherTableID => undefined');
t.is(log.shift(), 'set vc.2.|nextOrdinal 1');
t.is(log.shift(), 'set vc.2.|entryCount 0');
t.is(log.shift(), 'set watcherTableID o+d6/2');
t.is(log.shift(), 'get vom.rc.o+d6/2 => undefined');
t.is(log.shift(), 'set vom.rc.o+d6/2 1');
t.is(log.shift(), 'get watchedPromiseTableID => undefined');
t.is(log.shift(), 'set vc.3.|nextOrdinal 1');
t.is(log.shift(), 'set vc.3.|entryCount 0');
t.is(log.shift(), 'set watchedPromiseTableID o+d6/3');
t.is(log.shift(), 'get vom.rc.o+d6/3 => undefined');
t.is(log.shift(), 'set vom.rc.o+d6/3 1');
t.is(
log.shift(),
`set vom.vkind.10.descriptor {"kindID":"10","tag":"thing"}`,
'set vom.vkind.10.descriptor {"kindID":"10","tag":"thing"}',
);
t.is(log.shift(), `set vom.vkind.11.descriptor {"kindID":"11","tag":"ref"}`);
t.deepEqual(log, []);
Expand All @@ -682,6 +696,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.${tbase}/1`, minThing('thing #1')],
[`vom.${tbase}/2`, minThing('thing #2')],
[`vom.${tbase}/3`, minThing('thing #3')],
Expand All @@ -691,8 +711,12 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// This is what the finalizer would do if the local reference was dropped and GC'd
Expand All @@ -718,6 +742,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.es.${tbase}/1`, 'r'],
[`vom.${tbase}/1`, minThing('thing #1')],
[`vom.${tbase}/2`, minThing('thing #2')],
Expand All @@ -728,8 +758,12 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// drop export -- should delete
Expand Down Expand Up @@ -759,6 +793,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.${tbase}/2`, minThing('thing #2')],
[`vom.${tbase}/3`, minThing('thing #3')],
[`vom.${tbase}/4`, minThing('thing #4')],
Expand All @@ -767,8 +807,12 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// case 2: export, drop export, drop local ref
Expand All @@ -786,6 +830,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.es.${tbase}/2`, 's'],
[`vom.${tbase}/2`, minThing('thing #2')],
[`vom.${tbase}/3`, minThing('thing #3')],
Expand All @@ -795,8 +845,12 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// drop local ref -- should delete
Expand All @@ -817,15 +871,25 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.${tbase}/3`, minThing('thing #3')],
[`vom.${tbase}/4`, minThing('thing #4')],
[`vom.${tbase}/5`, minThing('thing #5')],
[`vom.${tbase}/6`, minThing('thing #6')],
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// case 3: drop local ref with no prior export
Expand All @@ -847,14 +911,24 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.${tbase}/4`, minThing('thing #4')],
[`vom.${tbase}/5`, minThing('thing #5')],
[`vom.${tbase}/6`, minThing('thing #6')],
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);

// case 4: ref virtually, export, drop local ref, drop export
Expand All @@ -867,15 +941,25 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.${tbase}/4`, minThing('thing #4')],
[`vom.${tbase}/5`, minThing('thing #5')],
[`vom.${tbase}/6`, minThing('thing #6')],
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
[`vom.rc.${tbase}/4`, '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);
// export
setExportStatus(`${tbase}/4`, 'reachable');
Expand Down Expand Up @@ -909,6 +993,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.es.${tbase}/4`, 's'],
[`vom.es.${tbase}/5`, 'r'],
[`vom.${tbase}/4`, minThing('thing #4')],
Expand All @@ -917,10 +1007,14 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
[`vom.rc.${tbase}/4`, '1'],
[`vom.rc.${tbase}/5`, '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);
// drop local ref -- should not delete because ref'd virtually AND exported
pretendGC(`${tbase}/5`, false);
Expand All @@ -944,6 +1038,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.es.${tbase}/4`, 's'],
[`vom.es.${tbase}/5`, 's'],
[`vom.${tbase}/4`, minThing('thing #4')],
Expand All @@ -952,11 +1052,15 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
[`vom.rc.${tbase}/4`, '1'],
[`vom.rc.${tbase}/5`, '1'],
[`vom.rc.${tbase}/6`, '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);
// drop local ref -- should not delete because ref'd virtually
pretendGC(`${tbase}/6`, false);
Expand All @@ -966,6 +1070,12 @@ test('virtual object gc', t => {
t.deepEqual(dumpStore(), [
['kindIDID', '1'],
skit,
['vc.1.|entryCount', '0'],
['vc.1.|nextOrdinal', '1'],
['vc.2.|entryCount', '0'],
['vc.2.|nextOrdinal', '1'],
['vc.3.|entryCount', '0'],
['vc.3.|nextOrdinal', '1'],
[`vom.es.${tbase}/4`, 's'],
[`vom.es.${tbase}/5`, 's'],
[`vom.${tbase}/4`, minThing('thing #4')],
Expand All @@ -974,11 +1084,15 @@ test('virtual object gc', t => {
[`vom.${tbase}/7`, minThing('thing #7')],
[`vom.${tbase}/8`, minThing('thing #8')],
[`vom.${tbase}/9`, minThing('thing #9')],
['vom.rc.o+d6/2', '1'],
['vom.rc.o+d6/3', '1'],
[`vom.rc.${tbase}/4`, '1'],
[`vom.rc.${tbase}/5`, '1'],
[`vom.rc.${tbase}/6`, '1'],
['vom.vkind.10.descriptor', '{"kindID":"10","tag":"thing"}'],
['vom.vkind.11.descriptor', '{"kindID":"11","tag":"ref"}'],
['watchedPromiseTableID', 'o+d6/3'],
['watcherTableID', 'o+d6/2'],
]);
});

Expand Down
17 changes: 15 additions & 2 deletions packages/swingset-liveslots/tools/fakeVirtualSupport.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
/* eslint-disable max-classes-per-file */
import { makeMarshal } from '@endo/marshal';
import { assert } from '@agoric/assert';
import { parseVatSlot } from '../src/parseVatSlots.js';
import { isPromise } from '@endo/promise-kit';

import { parseVatSlot } from '../src/parseVatSlots.js';
import { makeVirtualReferenceManager } from '../src/virtualReferences.js';
import { makeWatchedPromiseManager } from '../src/watchedPromises.js';
import { makeFakeVirtualObjectManager } from './fakeVirtualObjectManager.js';
Expand Down Expand Up @@ -158,6 +159,14 @@ export function makeFakeLiveSlotsStuff(options = {}) {
return exportID;
}

// different starting point for more distinct IDs
let nextPromiseID = 7;
function allocatePromiseID() {
const promiseID = nextPromiseID;
nextPromiseID += 1;
return promiseID;
}

let nextCollectionID = 1;
function allocateCollectionID() {
const collectionID = nextCollectionID;
Expand Down Expand Up @@ -193,7 +202,9 @@ export function makeFakeLiveSlotsStuff(options = {}) {

function convertValToSlot(val) {
if (!valToSlot.has(val)) {
const slot = `o+${allocateExportID()}`;
const slot = isPromise(val)
? `p+${allocatePromiseID()}`
: `o+${allocateExportID()}`;
valToSlot.set(val, slot);
setValForSlot(slot, val);
}
Expand Down Expand Up @@ -311,6 +322,7 @@ export function makeFakeWatchedPromiseManager(
maybeExportPromise: fakeStuff.maybeExportPromise,
});
}

/**
* Configure virtual stuff with relaxed durability rules and fake liveslots
*
Expand All @@ -331,6 +343,7 @@ export function makeFakeVirtualStuff(options = {}) {
fakeStuff.setVrm(vrm);
const cm = makeFakeCollectionManager(vrm, fakeStuff, actualOptions);
const wpm = makeFakeWatchedPromiseManager(vrm, vom, cm, fakeStuff);
wpm.preparePromiseWatcherTables();
return { fakeStuff, vrm, vom, cm, wpm };
}

Expand Down

0 comments on commit f31ccb0

Please sign in to comment.