Full SDK workspace: core, contracts, sdk, cli, browser-host, browser-kit, federation, omega-core, oracle, self-healing, strategies, tools, emacs. Clean extraction from the development monorepo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
131 lines
4.2 KiB
TypeScript
131 lines
4.2 KiB
TypeScript
/**
|
|
* 08J: Multi-Runtime Integration Test
|
|
*
|
|
* Tests multiple runtimes sharing a realm with shard isolation.
|
|
*/
|
|
|
|
import { describe, it, beforeEach } from 'node:test';
|
|
import { strict as assert } from 'node:assert';
|
|
import {
|
|
InMemoryFilterBroker,
|
|
ShardAllocator,
|
|
getMxIngressTopic,
|
|
} from '@open-matrix/federation';
|
|
|
|
describe('08J: Multi-Runtime Integration', () => {
|
|
let allocator: ShardAllocator;
|
|
|
|
beforeEach(() => {
|
|
allocator = new ShardAllocator();
|
|
});
|
|
|
|
describe('Shard Allocation', () => {
|
|
it('allocates unique shards per realm', () => {
|
|
const shard1 = allocator.allocate('flowpad-1');
|
|
const shard2 = allocator.allocate('flowpad-2');
|
|
// Different base realms, both get 00
|
|
assert.equal(shard1, '00');
|
|
assert.equal(shard2, '00');
|
|
});
|
|
|
|
it('same realm returns same shard', () => {
|
|
const shard1 = allocator.allocate('flowpad');
|
|
const shard2 = allocator.allocate('flowpad');
|
|
assert.equal(shard1, shard2);
|
|
});
|
|
});
|
|
|
|
describe('Ingress Topic Format', () => {
|
|
it('generates correct ingress topic for shard', () => {
|
|
const topic1 = getMxIngressTopic('flowpad.tab-abc', '01');
|
|
const topic2 = getMxIngressTopic('flowpad.tab-xyz', '02');
|
|
|
|
assert.equal(topic1, 'flowpad.tab-abc.$ingress.01');
|
|
assert.equal(topic2, 'flowpad.tab-xyz.$ingress.02');
|
|
});
|
|
});
|
|
|
|
describe('Tab Realm Isolation', () => {
|
|
it('messages to tab-abc do not reach tab-xyz', async () => {
|
|
const broker = new InMemoryFilterBroker();
|
|
|
|
// Two tabs with different tab realms
|
|
const tab1Realm = 'flowpad.tab-abc';
|
|
const tab2Realm = 'flowpad.tab-xyz';
|
|
|
|
const tab1Messages: string[] = [];
|
|
const tab2Messages: string[] = [];
|
|
|
|
// Subscribe to respective ingress
|
|
broker.subscribe(`${tab1Realm}.$ingress.01`, (topic, msg) => {
|
|
tab1Messages.push(msg);
|
|
});
|
|
broker.subscribe(`${tab2Realm}.$ingress.02`, (topic, msg) => {
|
|
tab2Messages.push(msg);
|
|
});
|
|
|
|
// Send to tab1 only
|
|
broker.publish(`${tab1Realm}.$ingress.01`, JSON.stringify({ data: 'for-tab1' }));
|
|
|
|
// Allow async processing
|
|
await new Promise((r) => setTimeout(r, 10));
|
|
|
|
assert.equal(tab1Messages.length, 1, 'Tab1 should receive message');
|
|
assert.equal(tab2Messages.length, 0, 'Tab2 should not receive message');
|
|
});
|
|
|
|
it('wildcard subscription receives from all shards', async () => {
|
|
const broker = new InMemoryFilterBroker();
|
|
const realm = 'flowpad';
|
|
const received: string[] = [];
|
|
|
|
// Subscribe with wildcard for all shards
|
|
broker.subscribe(`${realm}.$ingress.+`, (topic, msg) => {
|
|
received.push(msg);
|
|
});
|
|
|
|
// Send to different shards
|
|
broker.publish(`${realm}.$ingress.01`, JSON.stringify({ shard: '01' }));
|
|
broker.publish(`${realm}.$ingress.02`, JSON.stringify({ shard: '02' }));
|
|
broker.publish(`${realm}.$ingress.03`, JSON.stringify({ shard: '03' }));
|
|
|
|
await new Promise((r) => setTimeout(r, 10));
|
|
|
|
assert.equal(received.length, 3, 'Should receive from all shards');
|
|
});
|
|
});
|
|
|
|
describe('Shard-Specific Routing', () => {
|
|
it('messages route to correct shard', async () => {
|
|
const broker = new InMemoryFilterBroker();
|
|
const realm = 'test-realm';
|
|
|
|
const shard01Messages: string[] = [];
|
|
const shard02Messages: string[] = [];
|
|
|
|
// Subscribe to specific shards
|
|
broker.subscribe(`${realm}.$ingress.01`, (topic, msg) => {
|
|
shard01Messages.push(msg);
|
|
});
|
|
broker.subscribe(`${realm}.$ingress.02`, (topic, msg) => {
|
|
shard02Messages.push(msg);
|
|
});
|
|
|
|
// Send to shard 01
|
|
broker.publish(`${realm}.$ingress.01`, JSON.stringify({ target: '01' }));
|
|
|
|
// Send to shard 02
|
|
broker.publish(`${realm}.$ingress.02`, JSON.stringify({ target: '02' }));
|
|
|
|
await new Promise((r) => setTimeout(r, 10));
|
|
|
|
assert.equal(shard01Messages.length, 1, 'Shard 01 should receive one message');
|
|
assert.equal(shard02Messages.length, 1, 'Shard 02 should receive one message');
|
|
|
|
// Verify correct routing
|
|
assert.ok(shard01Messages[0].includes('"target":"01"'), 'Shard 01 got correct message');
|
|
assert.ok(shard02Messages[0].includes('"target":"02"'), 'Shard 02 got correct message');
|
|
});
|
|
});
|
|
});
|