/** * 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'); }); }); });