From bcfd68d6db40021c3a46a1f1e5296a2f974cc6ef Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sun, 27 Mar 2022 15:17:13 -0700 Subject: [PATCH] fix(swingset): initializeKindHandleKind early enough to support durables Previously, `kindIDID` (the ID of the virtual object Kind that is used to hold the KindHandles we need for durable kinds) was allocated on-demand, the first time `makeKindHandle()` was called. The ID it received (and the ID of everything allocate afterwards) thus depended upon if/when userspace decided to use `makeKindHandle()`. In addition, `vrm.registerKind()` for the KindHandle kind was not called until `kindIDID` itself was allocated. This doesn't necessarily happen at all in the version-2 of a vat (i.e. if v2 doesn't define any additional durable kinds), and can't be relied upon to happen before v2 needs to deserialize the KindHandles that live in the 'baggage'. So this commit changes liveslots to factor out the initialization and registration into a new `initializeKindHandleKind` function, and arranges to call it during `startVat()`. Several "fake" test harnesses in `tools/` were updated to call it as they build their stuff. test-gc-kernel.js was updated to sort the extracted vrefs numerically, which was allowing the previous version of this test to pass despite having the wrong object IDs. refs #1848 --- packages/SwingSet/src/liveslots/liveslots.js | 1 + .../src/liveslots/virtualObjectManager.js | 16 ++++++--- packages/SwingSet/test/gc/test-gc-vat.js | 4 +-- packages/SwingSet/test/stores/test-storeGC.js | 20 ++++++----- packages/SwingSet/test/test-baggage.js | 10 +++--- packages/SwingSet/test/test-gc-kernel.js | 31 +++++++++++++--- packages/SwingSet/test/test-liveslots.js | 6 ++-- packages/SwingSet/test/test-vpid-liveslots.js | 4 +-- .../vat-admin/terminate/test-terminate.js | 2 +- .../virtualObjects/test-representatives.js | 25 ++++++------- .../virtualObjects/test-virtualObjectGC.js | 34 ++++++++---------- .../test-virtualObjectManager.js | 35 ++++++++++++++----- .../tools/fakeVirtualObjectManager.js | 2 ++ packages/SwingSet/tools/fakeVirtualSupport.js | 2 ++ 14 files changed, 122 insertions(+), 70 deletions(-) diff --git a/packages/SwingSet/src/liveslots/liveslots.js b/packages/SwingSet/src/liveslots/liveslots.js index 4f3a1531109d..f0eaccf848f6 100644 --- a/packages/SwingSet/src/liveslots/liveslots.js +++ b/packages/SwingSet/src/liveslots/liveslots.js @@ -1228,6 +1228,7 @@ function build( } initializeIDCounters(); + vom.initializeKindHandleKind(); collectionManager.initializeStoreKindInfo(); const vatParameters = m.unserialize(vatParametersCapData); diff --git a/packages/SwingSet/src/liveslots/virtualObjectManager.js b/packages/SwingSet/src/liveslots/virtualObjectManager.js index 047585f07532..f0b050862721 100644 --- a/packages/SwingSet/src/liveslots/virtualObjectManager.js +++ b/packages/SwingSet/src/liveslots/virtualObjectManager.js @@ -659,6 +659,15 @@ export function makeVirtualObjectManager( let kindIDID; const kindDescriptors = new WeakMap(); + function initializeKindHandleKind() { + kindIDID = syscall.vatstoreGet('kindIDID'); + if (!kindIDID) { + kindIDID = `${allocateExportID()}`; + syscall.vatstoreSet('kindIDID', kindIDID); + } + vrm.registerKind(kindIDID, reanimateDurableKindID, () => null, true); + } + function reanimateDurableKindID(vobjID, _proforma) { const { subid: kindID } = parseVatSlot(vobjID); const raw = syscall.vatstoreGet(`vom.kind.${kindID}`); @@ -670,11 +679,7 @@ export function makeVirtualObjectManager( } const makeKindHandle = tag => { - if (!kindIDID) { - kindIDID = `${allocateExportID()}`; - syscall.vatstoreSet('kindIDID', kindIDID); - vrm.registerKind(kindIDID, reanimateDurableKindID, () => null, true); - } + assert(kindIDID, `initializeKindHandleKind not called yet`); const kindID = `${allocateExportID()}`; const kindIDvref = `o+${kindIDID}/${kindID}`; const durableKindDescriptor = harden({ kindID, tag }); @@ -712,6 +717,7 @@ export function makeVirtualObjectManager( }; return harden({ + initializeKindHandleKind, defineKind, defineDurableKind, makeKindHandle, diff --git a/packages/SwingSet/test/gc/test-gc-vat.js b/packages/SwingSet/test/gc/test-gc-vat.js index 5b4ee52f77a1..1d777159a758 100644 --- a/packages/SwingSet/test/gc/test-gc-vat.js +++ b/packages/SwingSet/test/gc/test-gc-vat.js @@ -134,8 +134,8 @@ test('forward to fake zoe', async t => { console.log(`targetID: ${targetID}`); // confirm that zoe is exporting it - t.is(findClist(c, zoeID, invitation), 'o+9'); - t.true(dumpClist(c).includes(`${invitation}/${zoeID}/o+9`)); + t.is(findClist(c, zoeID, invitation), 'o+10'); + t.true(dumpClist(c).includes(`${invitation}/${zoeID}/o+10`)); // confirm that vat-target has not seen it yet t.is(findClist(c, targetID, invitation), undefined); diff --git a/packages/SwingSet/test/stores/test-storeGC.js b/packages/SwingSet/test/stores/test-storeGC.js index 293581645a47..dfb08de7ce5e 100644 --- a/packages/SwingSet/test/stores/test-storeGC.js +++ b/packages/SwingSet/test/stores/test-storeGC.js @@ -201,7 +201,7 @@ function thingRefValString(vref) { const nullValString = JSON.stringify({ body: 'null', slots: [] }); function mapRef(idx) { - return `o+1/${idx}`; + return `o+2/${idx}`; // see 'assert known scalarMapStore ID' below } function mapRefArg(idx) { @@ -237,9 +237,9 @@ function validateCreateBaggage(v, idx) { ); validate(v, matchVatstoreSet(`vc.${idx}.|schemata`, baggageSchema)); validate(v, matchVatstoreSet(`vc.${idx}.|label`, 'baggage')); - validate(v, matchVatstoreSet('baggageID', 'o+5/1')); - validate(v, matchVatstoreGet('vom.rc.o+5/1', NONE)); - validate(v, matchVatstoreSet('vom.rc.o+5/1', '1')); + validate(v, matchVatstoreSet('baggageID', 'o+6/1')); + validate(v, matchVatstoreGet('vom.rc.o+6/1', NONE)); + validate(v, matchVatstoreSet('vom.rc.o+6/1', '1')); } function validateCreate(v, idx, isWeak = false) { @@ -466,12 +466,14 @@ function validateCreateHolder(v, idx) { function validateInit(v) { validate(v, matchVatstoreGet('idCounters', NONE)); + validate(v, matchVatstoreGet('kindIDID', NONE)); + validate(v, matchVatstoreSet('kindIDID', '1')); validate(v, matchVatstoreGet('storeKindIDTable', NONE)); validate( v, matchVatstoreSet( 'storeKindIDTable', - '{"scalarMapStore":1,"scalarWeakMapStore":2,"scalarSetStore":3,"scalarWeakSetStore":4,"scalarDurableMapStore":5,"scalarDurableWeakMapStore":6,"scalarDurableSetStore":7,"scalarDurableWeakSetStore":8}', + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', ), ); validate(v, matchVatstoreGet('baggageID', NONE)); @@ -531,8 +533,8 @@ test.serial('assert known scalarMapStore ID', async t => { const { testHooks } = await setupTestLiveslots(t, buildRootObject, 'bob', true); const id = testHooks.obtainStoreKindID('scalarMapStore'); - t.is(id, 1); - t.is(mapRef('INDEX'), 'o+1/INDEX'); + t.is(id, 2); + t.is(mapRef('INDEX'), 'o+2/INDEX'); }); // test 1: lerv -> Lerv -> LerV -> Lerv -> lerv @@ -1094,7 +1096,7 @@ test.serial('remotable refcount management 1', async t => { ); const base = mainHeldIdx; - const remotableRef = 'o+9'; + const remotableRef = 'o+10'; let rp = await dispatchMessage('makeAndHoldRemotable'); validateInit(v); @@ -1126,7 +1128,7 @@ test.serial('remotable refcount management 2', async t => { ); const base = mainHeldIdx; - const remotableRef = 'o+9'; + const remotableRef = 'o+10'; let rp = await dispatchMessage('makeAndHoldRemotable'); validateInit(v); diff --git a/packages/SwingSet/test/test-baggage.js b/packages/SwingSet/test/test-baggage.js index 139b78d8ce34..14c882921076 100644 --- a/packages/SwingSet/test/test-baggage.js +++ b/packages/SwingSet/test/test-baggage.js @@ -40,19 +40,21 @@ function validateCreateBaggage(v, idx) { ); validate(v, matchVatstoreSet(`vc.${idx}.|schemata`, baggageSchema)); validate(v, matchVatstoreSet(`vc.${idx}.|label`, 'baggage')); - validate(v, matchVatstoreSet('baggageID', 'o+5/1')); - validate(v, matchVatstoreGet('vom.rc.o+5/1', NONE)); - validate(v, matchVatstoreSet('vom.rc.o+5/1', '1')); + validate(v, matchVatstoreSet('baggageID', 'o+6/1')); + validate(v, matchVatstoreGet('vom.rc.o+6/1', NONE)); + validate(v, matchVatstoreSet('vom.rc.o+6/1', '1')); } function validateSetup(v) { validate(v, matchVatstoreGet('idCounters', NONE)); + validate(v, matchVatstoreGet('kindIDID', NONE)); + validate(v, matchVatstoreSet('kindIDID', '1')); validate(v, matchVatstoreGet('storeKindIDTable', NONE)); validate( v, matchVatstoreSet( 'storeKindIDTable', - '{"scalarMapStore":1,"scalarWeakMapStore":2,"scalarSetStore":3,"scalarWeakSetStore":4,"scalarDurableMapStore":5,"scalarDurableWeakMapStore":6,"scalarDurableSetStore":7,"scalarDurableWeakSetStore":8}', + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', ), ); validate(v, matchVatstoreGet('baggageID', NONE)); diff --git a/packages/SwingSet/test/test-gc-kernel.js b/packages/SwingSet/test/test-gc-kernel.js index d00aa25d5b41..4bce50654e91 100644 --- a/packages/SwingSet/test/test-gc-kernel.js +++ b/packages/SwingSet/test/test-gc-kernel.js @@ -3,9 +3,11 @@ import anylogger from 'anylogger'; import { test } from '../tools/prepare-test-env-ava.js'; +// eslint-disable-next-line import/order +import { assert } from '@agoric/assert'; import { waitUntilQuiescent } from '../src/lib-nodejs/waitUntilQuiescent.js'; import { createSHA256 } from '../src/lib-nodejs/hasher.js'; - +import { parseVatSlot } from '../src/lib/parseVatSlots.js'; import buildKernel from '../src/kernel/index.js'; import { initializeKernel } from '../src/controller/initializeKernel.js'; import { @@ -1019,6 +1021,25 @@ test('message to self', async t => { p.gcActionsAre([]); }); +function sortVrefs(vrefs) { + // returns ['o+8', 'o+9', 'o+10', 'o+11'] + function num(vref) { + const p = parseVatSlot(vref); + assert.equal(p.type, 'object'); + assert.equal(p.allocatedByVat, true); + assert.equal(p.virtual, false); + return p.id; + } + vrefs.sort((a, b) => Number(num(a) - num(b))); +} + +test('sortVrefs', t => { + const v1 = ['o+11', 'o+9', 'o+10', 'o+8']; + const exp = ['o+8', 'o+9', 'o+10', 'o+11']; + sortVrefs(v1); + t.deepEqual(v1, exp); +}); + test('terminated vat', async t => { // when a vat is terminated, anything it imported should be dropped, and // its exports should not cause problems when they are released @@ -1082,9 +1103,9 @@ test('terminated vat', async t => { // find the highest export: doomedExport1 / doomedExport1Presence let exports = Object.keys(vrefs).filter(vref => vref.startsWith('o+')); - exports.sort(); + sortVrefs(exports); const doomedExport1Vref = exports[exports.length - 1]; - t.is(doomedExport1Vref, 'o+9'); // arbitrary + t.is(doomedExport1Vref, 'o+10'); // arbitrary const doomedExport1Kref = vrefs[doomedExport1Vref]; // this should also be deleted // console.log(`doomedExport1Kref`, doomedExport1Kref); @@ -1105,9 +1126,9 @@ test('terminated vat', async t => { // now find the vref/kref for doomedExport2 vrefs = vrefsUsedByDoomed(); exports = Object.keys(vrefs).filter(vref => vref.startsWith('o+')); - exports.sort(); + sortVrefs(exports); const doomedExport2Vref = exports[exports.length - 1]; - t.is(doomedExport2Vref, 'o+9'); // arbitrary + t.is(doomedExport2Vref, 'o+11'); // arbitrary const doomedExport2Kref = vrefs[doomedExport2Vref]; [refcounts, owners] = getRefCountsAndOwners(); t.deepEqual(refcounts[doomedExport2Kref], [1, 1]); // from promise queue diff --git a/packages/SwingSet/test/test-liveslots.js b/packages/SwingSet/test/test-liveslots.js index 1a058684c16e..524be50ab7fc 100644 --- a/packages/SwingSet/test/test-liveslots.js +++ b/packages/SwingSet/test/test-liveslots.js @@ -752,7 +752,7 @@ test('GC syscall.dropImports', async t => { t.deepEqual(log.shift(), { type: 'vatstoreSet', key: 'idCounters', - value: '{"exportID":9,"collectionID":2,"promiseID":5}', + value: '{"exportID":10,"collectionID":2,"promiseID":5}', }); const l2 = log.shift(); t.deepEqual(l2, { @@ -1153,7 +1153,7 @@ test('GC dispatch.dropExports', async t => { t.deepEqual(log.shift(), { type: 'vatstoreSet', key: 'idCounters', - value: '{"exportID":10,"collectionID":2,"promiseID":5}', + value: '{"exportID":11,"collectionID":2,"promiseID":5}', }); t.deepEqual(log, []); @@ -1220,7 +1220,7 @@ test('GC dispatch.retireExports inhibits syscall.retireExports', async t => { t.deepEqual(log.shift(), { type: 'vatstoreSet', key: 'idCounters', - value: '{"exportID":10,"collectionID":2,"promiseID":5}', + value: '{"exportID":11,"collectionID":2,"promiseID":5}', }); t.deepEqual(log, []); diff --git a/packages/SwingSet/test/test-vpid-liveslots.js b/packages/SwingSet/test/test-vpid-liveslots.js index 018a1c9c5307..ba5a9c3448ac 100644 --- a/packages/SwingSet/test/test-vpid-liveslots.js +++ b/packages/SwingSet/test/test-vpid-liveslots.js @@ -179,7 +179,7 @@ async function doVatResolveCase1(t, mode) { const rootA = 'o+0'; const target1 = 'o-1'; const target2 = 'o-2'; - const localTarget = 'o+9'; + const localTarget = 'o+10'; const expectedP1 = 'p+5'; const expectedP2 = 'p+6'; const expectedP3 = 'p+7'; @@ -333,7 +333,7 @@ async function doVatResolveCase23(t, which, mode, stalls) { const rootA = 'o+0'; const target1 = 'o-1'; - const localTarget = 'o+9'; + const localTarget = 'o+10'; const p1 = 'p-8'; const expectedP2 = 'p+5'; const expectedP3 = 'p+6'; diff --git a/packages/SwingSet/test/vat-admin/terminate/test-terminate.js b/packages/SwingSet/test/vat-admin/terminate/test-terminate.js index 56645d3f9b98..b65505b7de3d 100644 --- a/packages/SwingSet/test/vat-admin/terminate/test-terminate.js +++ b/packages/SwingSet/test/vat-admin/terminate/test-terminate.js @@ -213,7 +213,7 @@ test('dead vat state removed', async t => { const kvStore = hostStorage.kvStore; t.is(kvStore.get('vat.dynamicIDs'), '["v6"]'); t.is(kvStore.get('ko26.owner'), 'v6'); - t.is(Array.from(kvStore.getKeys('v6.', 'v6/')).length, 19); + t.is(Array.from(kvStore.getKeys('v6.', 'v6/')).length, 20); controller.queueToVatRoot('bootstrap', 'phase2', capargs([])); await controller.run(); diff --git a/packages/SwingSet/test/virtualObjects/test-representatives.js b/packages/SwingSet/test/virtualObjects/test-representatives.js index ef1e429f2a1f..ed02b8a4c846 100644 --- a/packages/SwingSet/test/virtualObjects/test-representatives.js +++ b/packages/SwingSet/test/virtualObjects/test-representatives.js @@ -133,13 +133,13 @@ test.serial('exercise cache', async t => { await doSimple('holdThing', what); } function dataKey(num) { - return `v1.vs.vom.o+9/${num}`; + return `v1.vs.vom.o+10/${num}`; } function esKey(num) { - return `v1.vs.vom.es.o+9/${num}`; + return `v1.vs.vom.es.o+10/${num}`; } function rcKey(num) { - return `v1.vs.vom.rc.o+9/${num}`; + return `v1.vs.vom.rc.o+10/${num}`; } function thingVal(name) { return JSON.stringify({ @@ -381,21 +381,22 @@ test('virtual object gc', async t => { remainingVOs[key] = hostStorage.kvStore.get(key); } t.deepEqual(remainingVOs, { - 'v1.vs.baggageID': 'o+5/1', - 'v1.vs.idCounters': '{"exportID":10,"collectionID":2,"promiseID":8}', + 'v1.vs.baggageID': 'o+6/1', + 'v1.vs.idCounters': '{"exportID":11,"collectionID":2,"promiseID":8}', + 'v1.vs.kindIDID': '1', 'v1.vs.storeKindIDTable': - '{"scalarMapStore":1,"scalarWeakMapStore":2,"scalarSetStore":3,"scalarWeakSetStore":4,"scalarDurableMapStore":5,"scalarDurableWeakMapStore":6,"scalarDurableSetStore":7,"scalarDurableWeakSetStore":8}', + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', 'v1.vs.vc.1.|entryCount': '0', 'v1.vs.vc.1.|label': 'baggage', 'v1.vs.vc.1.|nextOrdinal': '1', 'v1.vs.vc.1.|schemata': '{"body":"[{\\"@qclass\\":\\"tagged\\",\\"tag\\":\\"match:kind\\",\\"payload\\":\\"string\\"}]","slots":[]}', - 'v1.vs.vom.es.o+9/3': 'r', - 'v1.vs.vom.o+9/2': '{"label":{"body":"\\"thing #2\\"","slots":[]}}', - 'v1.vs.vom.o+9/3': '{"label":{"body":"\\"thing #3\\"","slots":[]}}', - 'v1.vs.vom.o+9/8': '{"label":{"body":"\\"thing #8\\"","slots":[]}}', - 'v1.vs.vom.o+9/9': '{"label":{"body":"\\"thing #9\\"","slots":[]}}', - 'v1.vs.vom.rc.o+5/1': '1', + 'v1.vs.vom.es.o+10/3': 'r', + 'v1.vs.vom.o+10/2': '{"label":{"body":"\\"thing #2\\"","slots":[]}}', + 'v1.vs.vom.o+10/3': '{"label":{"body":"\\"thing #3\\"","slots":[]}}', + 'v1.vs.vom.o+10/8': '{"label":{"body":"\\"thing #8\\"","slots":[]}}', + 'v1.vs.vom.o+10/9': '{"label":{"body":"\\"thing #9\\"","slots":[]}}', + 'v1.vs.vom.rc.o+6/1': '1', }); }); diff --git a/packages/SwingSet/test/virtualObjects/test-virtualObjectGC.js b/packages/SwingSet/test/virtualObjects/test-virtualObjectGC.js index 2302cc7481b1..4230d7ad4cb7 100644 --- a/packages/SwingSet/test/virtualObjects/test-virtualObjectGC.js +++ b/packages/SwingSet/test/virtualObjects/test-virtualObjectGC.js @@ -168,9 +168,11 @@ function stateKey(vref) { return `vom.${base(vref)}`; } -const unfacetedThingKindID = 'o+9'; -const facetedThingKindID = 'o+10'; -const holderKindID = 'o+11'; +const unfacetedThingKindID = 'o+10'; +const facetedThingKindID = 'o+11'; +const holderKindID = 'o+12'; + +const remotableID = 'o+14'; function thingVref(isf, instance) { return `${isf ? facetedThingKindID : unfacetedThingKindID}/${instance}`; @@ -454,19 +456,21 @@ function validateCreateBaggage(v, idx) { ); validate(v, matchVatstoreSet(`vc.${idx}.|schemata`, baggageSchema)); validate(v, matchVatstoreSet(`vc.${idx}.|label`, 'baggage')); - validate(v, matchVatstoreSet('baggageID', 'o+5/1')); - validate(v, matchVatstoreGet(rcKey('o+5/1'), NONE)); - validate(v, matchVatstoreSet(rcKey('o+5/1'), '1')); + validate(v, matchVatstoreSet('baggageID', 'o+6/1')); + validate(v, matchVatstoreGet(rcKey('o+6/1'), NONE)); + validate(v, matchVatstoreSet(rcKey('o+6/1'), '1')); } function validateSetup(v) { validate(v, matchVatstoreGet('idCounters', NONE)); + validate(v, matchVatstoreGet('kindIDID', NONE)); + validate(v, matchVatstoreSet('kindIDID', '1')); validate(v, matchVatstoreGet('storeKindIDTable', NONE)); validate( v, matchVatstoreSet( 'storeKindIDTable', - '{"scalarMapStore":1,"scalarWeakMapStore":2,"scalarSetStore":3,"scalarWeakSetStore":4,"scalarDurableMapStore":5,"scalarDurableWeakMapStore":6,"scalarDurableSetStore":7,"scalarDurableWeakSetStore":8}', + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', ), ); validate(v, matchVatstoreGet('baggageID', NONE)); @@ -1170,7 +1174,7 @@ test.serial('VO multifacet markers only', async t => { 'bob', true, ); - const thing = 'o+12/1'; + const thing = 'o+13/1'; const thingCapdata = JSON.stringify({ unused: capdata('uncared for') }); // lerv -> Lerv Create facets @@ -1303,18 +1307,13 @@ async function voRefcountManagementTest3(t, isf) { validate(v, matchVatstoreSet(stateKey(`${holderKindID}/4`), heldHolderValue(`${holderKindID}/3`))); validate(v, matchVatstoreGet(stateKey(cacheDisplacerVref), cacheObjValue)); validateReturned(v, rp); - if (isf) { - validate(v, matchVatstoreGet(rcKey(thing), '1')); - validate(v, matchVatstoreGet(esKey(thing), NONE)); - } + validate(v, matchVatstoreGet(rcKey(thing), '1')); + validate(v, matchVatstoreGet(esKey(thing), NONE)); + validate(v, matchVatstoreGet(rcKey(`${holderKindID}/2`), '1')); validate(v, matchVatstoreGet(esKey(`${holderKindID}/2`), NONE)); validate(v, matchVatstoreGet(rcKey(`${holderKindID}/3`), '1')); validate(v, matchVatstoreGet(esKey(`${holderKindID}/3`), NONE)); - if (!isf) { - validate(v, matchVatstoreGet(rcKey(thing), '1')); - validate(v, matchVatstoreGet(esKey(thing), NONE)); - } validateDone(v); rp = await dispatchMessage('finishDropHolders'); @@ -1445,7 +1444,6 @@ test.serial('presence refcount management 2', async t => { // prettier-ignore test.serial('remotable refcount management 1', async t => { const { v, dispatchMessage } = await setupTestLiveslots(t, buildRootObject, 'bob', true); - const remotableID = 'o+13'; let rp = await dispatchMessage('makeAndHoldRemotable'); validateSetup(v); @@ -1478,7 +1476,6 @@ test.serial('remotable refcount management 1', async t => { // prettier-ignore test.serial('remotable refcount management 2', async t => { const { v, dispatchMessage } = await setupTestLiveslots(t, buildRootObject, 'bob', true); - const remotableID = 'o+13'; let rp = await dispatchMessage('makeAndHoldRemotable'); validateSetup(v); @@ -1580,7 +1577,6 @@ test.serial('verify presence weak key GC', async t => { test.serial('VO holding non-VO', async t => { const { v, dispatchMessage, dispatchDropExports, dispatchRetireExports } = await setupTestLiveslots(t, buildRootObject, 'bob', true); - const remotableID = 'o+13'; // lerv -> Lerv Create non-VO let rp = await dispatchMessage('makeAndHoldRemotable'); diff --git a/packages/SwingSet/test/virtualObjects/test-virtualObjectManager.js b/packages/SwingSet/test/virtualObjects/test-virtualObjectManager.js index 05343c074abe..6151868bf407 100644 --- a/packages/SwingSet/test/virtualObjects/test-virtualObjectManager.js +++ b/packages/SwingSet/test/virtualObjects/test-virtualObjectManager.js @@ -115,7 +115,7 @@ test('multifaceted virtual objects', t => { }; }, ); - const kid = 'o+1'; + const kid = 'o+2'; const { incr, decr } = makeMultiThing('foo'); t.is(incr.getName(), 'foo'); t.is(incr.getCount(), 0); @@ -128,6 +128,8 @@ test('multifaceted virtual objects', t => { decr.dec(); t.is(decr.getCount(), 1); const other = makeMultiThing('other'); + t.is(log.shift(), `get kindIDID => undefined`); + t.is(log.shift(), `set kindIDID 1`); t.is(log.shift(), `set vom.${kid}/1 ${multiThingVal('foo', 1)}`); t.deepEqual(log, []); incr.inc(); @@ -148,12 +150,12 @@ test('virtual object operations', t => { const { defineKind, flushCache, dumpStore } = makeFakeVirtualObjectManager({ cacheSize: 3, log }); const makeThing = defineKind('thing', initThing, actualizeThing); - const tid = 'o+1'; + const tid = 'o+2'; const makeZot = defineKind('zot', initZot, actualizeZot); - const zid = 'o+2'; + const zid = 'o+3'; // phase 0: start - t.deepEqual(dumpStore(), []); + t.deepEqual(dumpStore(), [ ['kindIDID', '1']]); // phase 1: object creations const thing1 = makeThing('thing-1'); // [t1-0] @@ -164,6 +166,8 @@ test('virtual object operations', t => { // t3-0: 'thing-3' 200 0 const thing4 = makeThing('thing-4', 300); // [t4-0 t3-0 t2-0 t1-0] // t4-0: 'thing-4' 300 0 + t.is(log.shift(), `get kindIDID => undefined`); + t.is(log.shift(), `set kindIDID 1`); t.deepEqual(log, []); const zot1 = makeZot(23, 'Alice', 'is this on?'); // [z1-0 t4-0 t3-0 t2-0] evict t1-0 @@ -187,6 +191,7 @@ test('virtual object operations', t => { t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], [`vom.${tid}/1`, thingVal(0, 'thing-1', 0)], // =t1-0 [`vom.${tid}/2`, thingVal(100, 'thing-2', 0)], // =t2-0 [`vom.${tid}/3`, thingVal(200, 'thing-3', 0)], // =t3-0 @@ -247,6 +252,7 @@ test('virtual object operations', t => { t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], [`vom.${tid}/1`, thingVal(3, 'thing-1', 0)], // =t1-3 [`vom.${tid}/2`, thingVal(100, 'thing-2', 0)], // =t2-0 [`vom.${tid}/3`, thingVal(200, 'thing-3', 0)], // =t3-0 @@ -324,6 +330,7 @@ test('virtual object operations', t => { t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], [`vom.${tid}/1`, thingVal(4, 'thing-1', 0)], // =t1-4 [`vom.${tid}/2`, thingVal(100, 'thing-2', 0)], // =t2-0 [`vom.${tid}/3`, thingVal(200, 'thing-3', 0)], // =t3-0 @@ -349,6 +356,7 @@ test('virtual object operations', t => { t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], [`vom.${tid}/1`, thingVal(5, 'thing-1', 0)], // =t1-5 [`vom.${tid}/2`, thingVal(100, 'thing-2', 0)], // =t2-0 [`vom.${tid}/3`, thingVal(201, 'thing-3', 0)], // =t3-1 @@ -411,10 +419,9 @@ test('durable kind IDs can be reanimated', t => { // Create a durable kind ID, but don't use it yet let kindHandle = makeKindHandle('testkind'); - t.is(log.shift(), 'set kindIDID 9'); t.is(log.shift(), 'set vom.kind.10 {"kindID":"10","tag":"testkind"}'); t.deepEqual(log, []); - const khid = `o+9/10`; + const khid = `o+1/10`; // Store it in the store without having used it placeToPutIt.init('savedKindID', kindHandle); @@ -465,7 +472,7 @@ test('virtual object gc', t => { const { deleteEntry, dumpStore } = fakeStuff; const makeThing = defineKind('thing', initThing, actualizeThing); - const tbase = 'o+9'; + const tbase = 'o+10'; const makeRef = defineKind( 'ref', value => ({ value }), @@ -476,9 +483,11 @@ test('virtual object gc', t => { }), ); + t.is(log.shift(), `get kindIDID => undefined`); + t.is(log.shift(), `set kindIDID 1`); const skit = [ 'storeKindIDTable', - '{"scalarMapStore":1,"scalarWeakMapStore":2,"scalarSetStore":3,"scalarWeakSetStore":4,"scalarDurableMapStore":5,"scalarDurableWeakMapStore":6,"scalarDurableSetStore":7,"scalarDurableWeakSetStore":8}', + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', ]; t.is(log.shift(), `get storeKindIDTable => undefined`); t.is(log.shift(), `set ${skit[0]} ${skit[1]}`); @@ -497,6 +506,7 @@ test('virtual object gc', t => { t.is(log.shift(), `set vom.${tbase}/5 ${minThing('thing #5')}`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.${tbase}/1`, minThing('thing #1')], [`vom.${tbase}/2`, minThing('thing #2')], @@ -523,6 +533,7 @@ test('virtual object gc', t => { t.is(log.shift(), `get vom.es.${tbase}/1 => r`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.es.${tbase}/1`, 'r'], [`vom.${tbase}/1`, minThing('thing #1')], @@ -546,6 +557,7 @@ test('virtual object gc', t => { t.is(log.shift(), `delete vom.es.${tbase}/1`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.${tbase}/2`, minThing('thing #2')], [`vom.${tbase}/3`, minThing('thing #3')], @@ -566,6 +578,7 @@ test('virtual object gc', t => { t.is(log.shift(), `get vom.rc.${tbase}/2 => undefined`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.es.${tbase}/2`, 's'], [`vom.${tbase}/2`, minThing('thing #2')], @@ -583,6 +596,7 @@ test('virtual object gc', t => { t.is(log.shift(), `delete vom.es.${tbase}/2`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.${tbase}/3`, minThing('thing #3')], [`vom.${tbase}/4`, minThing('thing #4')], @@ -600,6 +614,7 @@ test('virtual object gc', t => { t.is(log.shift(), `delete vom.es.${tbase}/3`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.${tbase}/4`, minThing('thing #4')], [`vom.${tbase}/5`, minThing('thing #5')], @@ -614,6 +629,7 @@ test('virtual object gc', t => { t.is(log.shift(), `set vom.${tbase}/6 ${minThing('thing #6')}`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.${tbase}/4`, minThing('thing #4')], [`vom.${tbase}/5`, minThing('thing #5')], @@ -651,6 +667,7 @@ test('virtual object gc', t => { t.is(log.shift(), `set vom.${tbase}/7 ${minThing('thing #7')}`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.es.${tbase}/4`, 's'], [`vom.es.${tbase}/5`, 'r'], @@ -682,6 +699,7 @@ test('virtual object gc', t => { t.is(log.shift(), `set vom.${tbase}/8 ${minThing('thing #8')}`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.es.${tbase}/4`, 's'], [`vom.es.${tbase}/5`, 's'], @@ -700,6 +718,7 @@ test('virtual object gc', t => { t.is(log.shift(), `get vom.es.${tbase}/6 => undefined`); t.deepEqual(log, []); t.deepEqual(dumpStore(), [ + ['kindIDID', '1'], skit, [`vom.es.${tbase}/4`, 's'], [`vom.es.${tbase}/5`, 's'], diff --git a/packages/SwingSet/tools/fakeVirtualObjectManager.js b/packages/SwingSet/tools/fakeVirtualObjectManager.js index 7dd46793f45a..27e6e3d2cfb9 100644 --- a/packages/SwingSet/tools/fakeVirtualObjectManager.js +++ b/packages/SwingSet/tools/fakeVirtualObjectManager.js @@ -15,6 +15,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff, options = {}) { const { cacheSize = 100 } = options; const { + initializeKindHandleKind, defineKind, defineDurableKind, makeKindHandle, @@ -33,6 +34,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff, options = {}) { ); const normalVOM = { + initializeKindHandleKind, defineKind, defineDurableKind, makeKindHandle, diff --git a/packages/SwingSet/tools/fakeVirtualSupport.js b/packages/SwingSet/tools/fakeVirtualSupport.js index 6c384e8442d7..f5efb28f0a00 100644 --- a/packages/SwingSet/tools/fakeVirtualSupport.js +++ b/packages/SwingSet/tools/fakeVirtualSupport.js @@ -249,6 +249,7 @@ export function makeFakeVirtualStuff(options = {}) { const fakeStuff = makeFakeLiveSlotsStuff(options); const vrm = makeFakeVirtualReferenceManager(fakeStuff); const vom = makeFakeVirtualObjectManager(vrm, fakeStuff, options); + vom.initializeKindHandleKind(); fakeStuff.setVrm(vrm); const cm = makeFakeCollectionManager(vrm, fakeStuff, options); return { fakeStuff, vrm, vom, cm }; @@ -258,6 +259,7 @@ export function makeStandaloneFakeVirtualObjectManager(options = {}) { const fakeStuff = makeFakeLiveSlotsStuff(options); const vrm = makeFakeVirtualReferenceManager(fakeStuff); const vom = makeFakeVirtualObjectManager(vrm, fakeStuff, options); + vom.initializeKindHandleKind(); fakeStuff.setVrm(vrm); return vom; }