/** * Layer 4: RPC Unit Tests - Internal Message Parsing * * Tests for the internal message format parsers and normalizers. * These form the foundation of the RPC layer. */ import test from 'node:test'; import assert from 'node:assert/strict'; import { parseInternalRequest, parseInternalReply, normalizeInternalReply, isJsonNullPayload, type InternalRequest, type InternalReply, } from '@open-matrix/federation/runtime/internal_messages'; // ============================================================================ // parseInternalRequest Tests // ============================================================================ test('parseInternalRequest: valid mxenv1 request', () => { const json = JSON.stringify({ correlationId: 'corr-123', replyTo: '_local.replies.emits.corr-123', params: { key: 'value' }, _mx: { fromRealm: 'flowpad', incomingProfile: 'mxenv1' }, }); const result = parseInternalRequest(json); assert.ok(result !== null); assert.equal(result.correlationId, 'corr-123'); assert.equal(result.replyTo, '_local.replies.emits.corr-123'); assert.deepEqual(result.params, { key: 'value' }); assert.equal(result._mx.fromRealm, 'flowpad'); assert.equal(result._mx.incomingProfile, 'mxenv1'); }); test('parseInternalRequest: valid matrix3 request', () => { const json = JSON.stringify({ correlationId: 'corr-456', replyTo: 'flowpad._local.replies.emits.corr-456', params: [1, 2, 3], _mx: { fromRealm: 'daemon@matrix-3', incomingProfile: 'matrix3' }, }); const result = parseInternalRequest(json); assert.ok(result !== null); assert.equal(result.correlationId, 'corr-456'); assert.equal(result._mx.fromRealm, 'daemon@matrix-3'); assert.equal(result._mx.incomingProfile, 'matrix3'); assert.deepEqual(result.params, [1, 2, 3]); }); test('parseInternalRequest: params can be any JSON value', () => { // null params const json1 = JSON.stringify({ correlationId: 'c1', replyTo: 'reply/topic', params: null, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); assert.ok(parseInternalRequest(json1) !== null); // string params const json2 = JSON.stringify({ correlationId: 'c2', replyTo: 'reply/topic', params: 'just a string', _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); const result2 = parseInternalRequest(json2); assert.ok(result2 !== null); assert.equal(result2.params, 'just a string'); // number params const json3 = JSON.stringify({ correlationId: 'c3', replyTo: 'reply/topic', params: 42, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); const result3 = parseInternalRequest(json3); assert.ok(result3 !== null); assert.equal(result3.params, 42); // boolean params const json4 = JSON.stringify({ correlationId: 'c4', replyTo: 'reply/topic', params: false, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); const result4 = parseInternalRequest(json4); assert.ok(result4 !== null); assert.equal(result4.params, false); }); test('parseInternalRequest: rejects invalid JSON', () => { assert.equal(parseInternalRequest('not json'), null); assert.equal(parseInternalRequest('{malformed'), null); assert.equal(parseInternalRequest(''), null); }); test('parseInternalRequest: rejects non-object JSON', () => { assert.equal(parseInternalRequest('"string"'), null); assert.equal(parseInternalRequest('123'), null); assert.equal(parseInternalRequest('null'), null); assert.equal(parseInternalRequest('true'), null); assert.equal(parseInternalRequest('[]'), null); }); test('parseInternalRequest: rejects missing correlationId', () => { const json = JSON.stringify({ replyTo: 'reply/topic', params: {}, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects non-string correlationId', () => { const json = JSON.stringify({ correlationId: 123, replyTo: 'reply/topic', params: {}, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects missing replyTo', () => { const json = JSON.stringify({ correlationId: 'c', params: {}, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects non-string replyTo', () => { const json = JSON.stringify({ correlationId: 'c', replyTo: { url: 'topic' }, params: {}, _mx: { fromRealm: 'r', incomingProfile: 'mxenv1' }, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects missing _mx', () => { const json = JSON.stringify({ correlationId: 'c', replyTo: 'reply/topic', params: {}, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects non-object _mx', () => { const json = JSON.stringify({ correlationId: 'c', replyTo: 'reply/topic', params: {}, _mx: 'not an object', }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects missing _mx.fromRealm', () => { const json = JSON.stringify({ correlationId: 'c', replyTo: 'reply/topic', params: {}, _mx: { incomingProfile: 'mxenv1' }, }); assert.equal(parseInternalRequest(json), null); }); test('parseInternalRequest: rejects invalid _mx.incomingProfile', () => { const json = JSON.stringify({ correlationId: 'c', replyTo: 'reply/topic', params: {}, _mx: { fromRealm: 'r', incomingProfile: 'invalid' }, }); assert.equal(parseInternalRequest(json), null); }); // ============================================================================ // parseInternalReply Tests // ============================================================================ test('parseInternalReply: valid success reply', () => { const json = JSON.stringify({ correlationId: 'corr-123', ok: true, body: { data: 'result' }, }); const result = parseInternalReply(json); assert.ok(result !== null); assert.equal(result.correlationId, 'corr-123'); assert.equal(result.ok, true); assert.deepEqual(result.body, { data: 'result' }); }); test('parseInternalReply: valid error reply', () => { const json = JSON.stringify({ correlationId: 'corr-456', ok: false, body: null, error: { code: 'MX.TIMEOUT', message: 'Request timed out' }, }); const result = parseInternalReply(json); assert.ok(result !== null); assert.equal(result.correlationId, 'corr-456'); assert.equal(result.ok, false); assert.deepEqual(result.error, { code: 'MX.TIMEOUT', message: 'Request timed out' }); }); test('parseInternalReply: rejects invalid JSON', () => { assert.equal(parseInternalReply('not json'), null); assert.equal(parseInternalReply('{malformed'), null); }); test('parseInternalReply: rejects non-object JSON', () => { assert.equal(parseInternalReply('"string"'), null); assert.equal(parseInternalReply('123'), null); assert.equal(parseInternalReply('null'), null); assert.equal(parseInternalReply('[]'), null); }); test('parseInternalReply: rejects missing correlationId', () => { const json = JSON.stringify({ ok: true, body: {} }); assert.equal(parseInternalReply(json), null); }); test('parseInternalReply: rejects non-string correlationId', () => { const json = JSON.stringify({ correlationId: 123, ok: true, body: {} }); assert.equal(parseInternalReply(json), null); }); test('parseInternalReply: rejects missing ok', () => { const json = JSON.stringify({ correlationId: 'c', body: {} }); assert.equal(parseInternalReply(json), null); }); test('parseInternalReply: rejects non-boolean ok', () => { const json = JSON.stringify({ correlationId: 'c', ok: 'true', body: {} }); assert.equal(parseInternalReply(json), null); }); // ============================================================================ // normalizeInternalReply Tests (Tolerant Reader) // ============================================================================ test('normalizeInternalReply: full InternalReply format', () => { const raw = JSON.stringify({ correlationId: 'corr-full', ok: true, body: { value: 42 }, }); const result = normalizeInternalReply(raw, 'fallback'); assert.equal(result.correlationId, 'corr-full'); // Uses actual, not fallback assert.equal(result.ok, true); assert.deepEqual(result.body, { value: 42 }); }); test('normalizeInternalReply: semi reply with ok:true and body', () => { const raw = JSON.stringify({ ok: true, body: { semi: 'reply' }, }); const result = normalizeInternalReply(raw, 'fallback-corr'); assert.equal(result.correlationId, 'fallback-corr'); // Uses fallback assert.equal(result.ok, true); assert.deepEqual(result.body, { semi: 'reply' }); }); test('normalizeInternalReply: semi reply with ok:false and error', () => { const raw = JSON.stringify({ ok: false, error: { code: 'ERR', message: 'Something failed' }, }); const result = normalizeInternalReply(raw, 'fallback-corr'); assert.equal(result.ok, false); // Implementation includes details: undefined when not provided assert.deepEqual(result.error, { code: 'ERR', message: 'Something failed', details: undefined }); }); test('normalizeInternalReply: simple result object { result: ... }', () => { const raw = JSON.stringify({ result: [1, 2, 3], }); const result = normalizeInternalReply(raw, 'fallback-corr'); assert.equal(result.correlationId, 'fallback-corr'); assert.equal(result.ok, true); assert.deepEqual(result.body, [1, 2, 3]); }); test('normalizeInternalReply: when no ok field, result field triggers success path', () => { // When ok is NOT present but result IS present, the implementation // uses the dedicated 'result' handler path which returns result directly // (doesn't go through pickBody which would prefer body) const raw = JSON.stringify({ result: 'from-result', body: 'from-body', // This is ignored when no 'ok' field }); const result = normalizeInternalReply(raw, 'fb'); // Per implementation: if (!'ok' in parsed && 'result' in parsed) => body = result assert.equal(result.body, 'from-result'); }); test('normalizeInternalReply: arbitrary object is treated as successful body', () => { const raw = JSON.stringify({ foo: 'bar', num: 123, }); const result = normalizeInternalReply(raw, 'fallback'); assert.equal(result.ok, true); assert.deepEqual(result.body, { foo: 'bar', num: 123 }); }); test('normalizeInternalReply: object with error shape but no ok:false is still success', () => { // Per the implementation comment: "we do NOT infer failure without ok=false" const raw = JSON.stringify({ error: { code: 'X', message: 'Y' }, }); const result = normalizeInternalReply(raw, 'fb'); assert.equal(result.ok, true); // The whole object becomes the body since no ok field assert.deepEqual(result.body, { error: { code: 'X', message: 'Y' } }); }); test('normalizeInternalReply: non-object JSON values', () => { // Array const r1 = normalizeInternalReply('[1,2,3]', 'fb'); assert.equal(r1.ok, true); assert.deepEqual(r1.body, [1, 2, 3]); // Number const r2 = normalizeInternalReply('42', 'fb'); assert.equal(r2.ok, true); assert.equal(r2.body, 42); // String const r3 = normalizeInternalReply('"hello"', 'fb'); assert.equal(r3.ok, true); assert.equal(r3.body, 'hello'); // Boolean const r4 = normalizeInternalReply('true', 'fb'); assert.equal(r4.ok, true); assert.equal(r4.body, true); // JSON null const r5 = normalizeInternalReply('null', 'fb'); assert.equal(r5.ok, true); assert.equal(r5.body, null); }); test('normalizeInternalReply: invalid JSON treated as raw string body', () => { const result = normalizeInternalReply('not valid json at all', 'fb'); assert.equal(result.correlationId, 'fb'); assert.equal(result.ok, true); assert.equal(result.body, 'not valid json at all'); }); test('normalizeInternalReply: error details are preserved', () => { const raw = JSON.stringify({ ok: false, error: { code: 'MX.AUTH.FORBIDDEN', message: 'Access denied', details: { requiredScope: 'admin', actualScope: 'user' }, }, }); const result = normalizeInternalReply(raw, 'fb'); assert.equal(result.ok, false); assert.deepEqual(result.error, { code: 'MX.AUTH.FORBIDDEN', message: 'Access denied', details: { requiredScope: 'admin', actualScope: 'user' }, }); }); test('normalizeInternalReply: incomplete error (missing code/message) is not picked', () => { const raw = JSON.stringify({ ok: false, error: { details: 'no code or message' }, }); const result = normalizeInternalReply(raw, 'fb'); assert.equal(result.ok, false); assert.equal(result.error, undefined); // Error not picked due to missing required fields }); // ============================================================================ // isJsonNullPayload Tests // ============================================================================ test('isJsonNullPayload: detects JSON null', () => { assert.equal(isJsonNullPayload('null'), true); assert.equal(isJsonNullPayload(' null '), true); // With whitespace assert.equal(isJsonNullPayload('\tnull\n'), true); }); test('isJsonNullPayload: rejects non-null values', () => { assert.equal(isJsonNullPayload('true'), false); assert.equal(isJsonNullPayload('false'), false); assert.equal(isJsonNullPayload('0'), false); assert.equal(isJsonNullPayload('""'), false); assert.equal(isJsonNullPayload('{}'), false); assert.equal(isJsonNullPayload('[]'), false); assert.equal(isJsonNullPayload('"null"'), false); // String "null", not JSON null assert.equal(isJsonNullPayload('undefined'), false); }); // ============================================================================ // Protocol Compliance Tests // ============================================================================ test('protocol: InternalRequest must include _mx for routing metadata', () => { // This test verifies the protocol requirement that all internal requests // must carry routing metadata via the _mx field const validRequest: InternalRequest = { correlationId: 'test-123', replyTo: '_local.replies.emits.test-123', params: { action: 'test' }, _mx: { fromRealm: 'source-realm', incomingProfile: 'mxenv1', msgId: 'optional-msg-id', traceId: 'optional-trace-id', }, }; const json = JSON.stringify(validRequest); const parsed = parseInternalRequest(json); assert.ok(parsed !== null); assert.equal(parsed._mx.fromRealm, 'source-realm'); assert.equal(parsed._mx.incomingProfile, 'mxenv1'); assert.equal(parsed._mx.msgId, 'optional-msg-id'); assert.equal(parsed._mx.traceId, 'optional-trace-id'); }); test('protocol: InternalReply error shape follows MATRIX-PROTOCOL-6', () => { // Per MATRIX-PROTOCOL-6 Section 52, errors must have code and message const errorReply: InternalReply = { correlationId: 'err-001', ok: false, body: null, error: { code: 'MX.TIMEOUT', message: 'Request timed out after 5000ms', details: { timeoutMs: 5000, target: 'realm/component.accepts.method' }, }, }; const json = JSON.stringify(errorReply); const parsed = parseInternalReply(json); assert.ok(parsed !== null); assert.equal(parsed.ok, false); assert.ok(parsed.error !== undefined); // Verify normalized version also preserves error structure const normalized = normalizeInternalReply(json, 'fb'); assert.equal(normalized.ok, false); assert.equal(normalized.error?.code, 'MX.TIMEOUT'); assert.equal(normalized.error?.message, 'Request timed out after 5000ms'); });