Skip to content

Commit 9538b10

Browse files
rekmarksclaude
andcommitted
test(kernel-errors): add missing error code assertions
- Add ENDPOINT_UNREACHABLE and DELIVERY_FAILED test cases to KernelRouter tests - Tighten OBJECT_DELETED and BAD_PROMISE_RESOLUTION assertions from expect.anything() to check for specific error codes - Verify CONNECTION_LOST in handleRemoteGiveUp rejection payload - Verify PEER_RESTARTED in handleIncarnationChange rejection payload Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9a1ce19 commit 9538b10

2 files changed

Lines changed: 126 additions & 9 deletions

File tree

packages/ocap-kernel/src/KernelRouter.test.ts

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,18 @@ describe('KernelRouter', () => {
243243
'kp1',
244244
'deliver|splat|result',
245245
);
246-
// Verify the promise was rejected with 'no vat'
246+
// Verify the promise was rejected with OBJECT_DELETED
247247
expect(kernelQueue.resolvePromises).toHaveBeenCalledWith(
248248
undefined,
249249
expect.arrayContaining([
250-
expect.arrayContaining(['kp1', true, expect.anything()]),
250+
expect.arrayContaining([
251+
'kp1',
252+
true,
253+
expect.objectContaining({
254+
body: expect.stringContaining('[KERNEL:OBJECT_DELETED]'),
255+
slots: [],
256+
}),
257+
]),
251258
]),
252259
);
253260
});
@@ -319,11 +326,19 @@ describe('KernelRouter', () => {
319326
expect(endpointHandle.deliverMessage).not.toHaveBeenCalled();
320327
expect(result).toBeUndefined();
321328

322-
// Verify the result promise was rejected
329+
// Verify the result promise was rejected with BAD_PROMISE_RESOLUTION
323330
expect(kernelQueue.resolvePromises).toHaveBeenCalledWith(
324331
undefined,
325332
expect.arrayContaining([
326-
expect.arrayContaining(['kp2', true, expect.anything()]),
333+
expect.arrayContaining([
334+
'kp2',
335+
true,
336+
expect.objectContaining({
337+
body: expect.stringContaining(
338+
'[KERNEL:BAD_PROMISE_RESOLUTION]',
339+
),
340+
}),
341+
]),
327342
]),
328343
);
329344
});
@@ -369,6 +384,83 @@ describe('KernelRouter', () => {
369384
]),
370385
);
371386
});
387+
388+
it('splats message with ENDPOINT_UNREACHABLE when endpoint vanishes', async () => {
389+
const endpointId = 'v1';
390+
const target = 'ko123';
391+
(kernelStore.getOwner as unknown as MockInstance).mockReturnValueOnce(
392+
endpointId,
393+
);
394+
// getEndpoint throws (endpoint gone)
395+
(getEndpoint as unknown as MockInstance).mockImplementationOnce(() => {
396+
throw new Error('vat not found');
397+
});
398+
(
399+
kernelStore.getKernelPromise as unknown as MockInstance
400+
).mockReturnValueOnce({ decider: endpointId });
401+
402+
const message: Message = {
403+
methargs: { body: 'method args', slots: [] },
404+
result: 'kp1',
405+
};
406+
const sendItem: RunQueueItemSend = {
407+
type: 'send',
408+
target,
409+
message: message as unknown as SwingsetMessage,
410+
};
411+
412+
const result = await kernelRouter.deliver(sendItem);
413+
414+
expect(result).toBeUndefined();
415+
expect(kernelQueue.resolvePromises).toHaveBeenCalledWith(
416+
endpointId,
417+
expect.arrayContaining([
418+
expect.arrayContaining([
419+
'kp1',
420+
true,
421+
expect.objectContaining({
422+
body: expect.stringContaining('[KERNEL:ENDPOINT_UNREACHABLE]'),
423+
}),
424+
]),
425+
]),
426+
);
427+
});
428+
429+
it('rejects with DELIVERY_FAILED when endpoint.deliverMessage throws', async () => {
430+
const endpointId = 'v1';
431+
const target = 'ko123';
432+
(kernelStore.getOwner as unknown as MockInstance).mockReturnValueOnce(
433+
endpointId,
434+
);
435+
(
436+
endpointHandle.deliverMessage as unknown as MockInstance
437+
).mockRejectedValueOnce(new Error('queue full'));
438+
439+
const message: Message = {
440+
methargs: { body: 'method args', slots: [] },
441+
result: 'kp1',
442+
};
443+
const sendItem: RunQueueItemSend = {
444+
type: 'send',
445+
target,
446+
message: message as unknown as SwingsetMessage,
447+
};
448+
449+
await kernelRouter.deliver(sendItem);
450+
451+
expect(kernelQueue.resolvePromises).toHaveBeenCalledWith(
452+
endpointId,
453+
expect.arrayContaining([
454+
expect.arrayContaining([
455+
'kp1',
456+
true,
457+
expect.objectContaining({
458+
body: expect.stringContaining('[KERNEL:DELIVERY_FAILED]'),
459+
}),
460+
]),
461+
]),
462+
);
463+
});
372464
});
373465

374466
describe('notify', () => {

packages/ocap-kernel/src/remotes/kernel/RemoteManager.test.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,12 +771,31 @@ describe('RemoteManager', () => {
771771
expect(() => onRemoteGiveUp(peerId)).not.toThrow();
772772
});
773773

774-
it('handles remote give up and processes promises when they exist', () => {
774+
it('rejects kernel promises with CONNECTION_LOST when remote has promises', () => {
775775
const peerId = 'peer-with-promises';
776-
remoteManager.establishRemote(peerId);
776+
const remote = remoteManager.establishRemote(peerId);
777+
const { remoteId } = remote;
778+
779+
// Set up a promise where the remote is the decider
780+
const [kpid] = kernelStore.initKernelPromise();
781+
kernelStore.setPromiseDecider(kpid, remoteId);
782+
kernelKVStore.set(`cle.${remoteId}.p+1`, kpid);
783+
784+
const resolvePromisesSpy = vi.spyOn(mockKernelQueue, 'resolvePromises');
785+
777786
const initCall = vi.mocked(remoteComms.initRemoteComms).mock.calls[0];
778787
const onRemoteGiveUp = initCall?.[6] as (peerId: string) => void;
779-
expect(() => onRemoteGiveUp(peerId)).not.toThrow();
788+
onRemoteGiveUp(peerId);
789+
790+
expect(resolvePromisesSpy).toHaveBeenCalledWith(remoteId, [
791+
[
792+
kpid,
793+
true,
794+
expect.objectContaining({
795+
body: expect.stringContaining('[KERNEL:CONNECTION_LOST]'),
796+
}),
797+
],
798+
]);
780799
});
781800

782801
it('handles remote give up with no promises', () => {
@@ -829,9 +848,15 @@ describe('RemoteManager', () => {
829848
const onIncarnationChange = initCall?.[8] as (peerId: string) => void;
830849
onIncarnationChange(peerId);
831850

832-
// Should reject the promise with incarnation change error
851+
// Should reject the promise with PEER_RESTARTED error
833852
expect(resolvePromisesSpy).toHaveBeenCalledWith(remoteId, [
834-
[kpid, true, expect.objectContaining({ body: expect.any(String) })],
853+
[
854+
kpid,
855+
true,
856+
expect.objectContaining({
857+
body: expect.stringContaining('[KERNEL:PEER_RESTARTED]'),
858+
}),
859+
],
835860
]);
836861
});
837862

0 commit comments

Comments
 (0)