UNPKG

osc-mcp-server

Version:

Model Context Protocol server for OSC (Open Sound Control) endpoint management

329 lines 15.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const parser_1 = require("./parser"); const index_1 = require("../types/index"); describe('OSC Message Parser', () => { describe('parseOSCMessage', () => { it('should parse a simple message with no arguments', () => { const buffer = Buffer.alloc(12); let offset = 0; buffer.write('/test', offset); buffer.writeUInt8(0, offset + 5); offset += 8; buffer.write(',', offset); buffer.writeUInt8(0, offset + 1); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/test'); expect(result.message.typeTags).toBe(''); expect(result.message.arguments).toEqual([]); expect(result.message.sourceIp).toBe('127.0.0.1'); expect(result.message.sourcePort).toBe(8000); }); it('should parse a message with integer argument', () => { const buffer = Buffer.alloc(20); let offset = 0; buffer.write('/synth/freq', offset); buffer.writeUInt8(0, offset + 11); offset = 12; buffer.write(',i', offset); buffer.writeUInt8(0, offset + 2); offset = 16; buffer.writeInt32BE(440, offset); const result = (0, parser_1.parseOSCMessage)(buffer, '192.168.1.100', 57120); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/synth/freq'); expect(result.message.typeTags).toBe('i'); expect(result.message.arguments).toEqual([440]); }); it('should parse a message with float argument', () => { const buffer = Buffer.alloc(16); let offset = 0; buffer.write('/volume', offset); buffer.writeUInt8(0, offset + 7); offset += 8; buffer.write(',f', offset); buffer.writeUInt8(0, offset + 2); offset += 4; buffer.writeFloatBE(0.75, offset); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/volume'); expect(result.message.typeTags).toBe('f'); expect(result.message.arguments).toEqual([0.75]); }); it('should parse a message with string argument', () => { const buffer = Buffer.alloc(20); let offset = 0; buffer.write('/name', offset); buffer.writeUInt8(0, offset + 5); offset += 8; buffer.write(',s', offset); buffer.writeUInt8(0, offset + 2); offset += 4; buffer.write('test', offset); buffer.writeUInt8(0, offset + 4); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/name'); expect(result.message.typeTags).toBe('s'); expect(result.message.arguments).toEqual(['test']); }); it('should parse a message with blob argument', () => { const blobData = Buffer.from([0x01, 0x02, 0x03, 0x04]); const buffer = Buffer.alloc(20); let offset = 0; buffer.write('/data', offset); buffer.writeUInt8(0, offset + 5); offset += 8; buffer.write(',b', offset); buffer.writeUInt8(0, offset + 2); offset += 4; buffer.writeInt32BE(4, offset); offset += 4; blobData.copy(buffer, offset); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/data'); expect(result.message.typeTags).toBe('b'); expect(result.message.arguments).toHaveLength(1); expect(Buffer.isBuffer(result.message.arguments[0])).toBe(true); expect(result.message.arguments[0]).toEqual(blobData); }); it('should parse a message with multiple arguments', () => { const buffer = Buffer.alloc(28); let offset = 0; buffer.write('/multi', offset); buffer.writeUInt8(0, offset + 6); offset += 8; buffer.write(',ifs', offset); buffer.writeUInt8(0, offset + 4); offset += 8; buffer.writeInt32BE(123, offset); offset += 4; buffer.writeFloatBE(4.56, offset); offset += 4; buffer.write('hi', offset); buffer.writeUInt8(0, offset + 2); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/multi'); expect(result.message.typeTags).toBe('ifs'); expect(result.message.arguments).toHaveLength(3); expect(result.message.arguments[0]).toBe(123); expect(result.message.arguments[1]).toBeCloseTo(4.56); expect(result.message.arguments[2]).toBe('hi'); }); it('should handle unsupported type tags gracefully', () => { const buffer = Buffer.alloc(16); let offset = 0; buffer.write('/test', offset); buffer.writeUInt8(0, offset + 5); offset += 8; buffer.write(',xi', offset); buffer.writeUInt8(0, offset + 3); offset += 4; buffer.writeInt32BE(42, offset); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.error).toBeUndefined(); expect(result.message).toBeDefined(); expect(result.message.address).toBe('/test'); expect(result.message.typeTags).toBe('xi'); expect(result.message.arguments).toEqual([42]); }); it('should return error for message too short', () => { const buffer = Buffer.alloc(4); buffer.write('/hi'); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.message).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); expect(result.error.message).toContain('too short'); }); it('should return error for invalid address pattern', () => { const buffer = Buffer.alloc(12); let offset = 0; buffer.write('test', offset); buffer.writeUInt8(0, offset + 4); offset += 8; buffer.write(',', offset); buffer.writeUInt8(0, offset + 1); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.message).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); expect(result.error.message).toContain('must start with "/"'); }); it('should return error for missing type tags', () => { const buffer = Buffer.alloc(8); buffer.write('/test'); const result = (0, parser_1.parseOSCMessage)(buffer, '127.0.0.1', 8000); expect(result.message).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); }); describe('extractAddressPattern', () => { it('should extract valid address pattern', () => { const buffer = Buffer.alloc(8); buffer.write('/test'); buffer.writeUInt8(0, 5); const result = (0, parser_1.extractAddressPattern)(buffer, 0); expect(result.error).toBeUndefined(); expect(result.value).toBe('/test'); expect(result.nextOffset).toBe(8); }); it('should return error for address not starting with /', () => { const buffer = Buffer.alloc(8); buffer.write('test'); buffer.writeUInt8(0, 4); const result = (0, parser_1.extractAddressPattern)(buffer, 0); expect(result.value).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); it('should return error for non-null-terminated address', () => { const buffer = Buffer.alloc(8); buffer.fill(0x2f); const result = (0, parser_1.extractAddressPattern)(buffer, 0); expect(result.value).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); }); describe('extractTypeTags', () => { it('should extract valid type tags', () => { const buffer = Buffer.alloc(8); buffer.write(',ifs'); buffer.writeUInt8(0, 4); const result = (0, parser_1.extractTypeTags)(buffer, 0); expect(result.error).toBeUndefined(); expect(result.value).toBe('ifs'); expect(result.nextOffset).toBe(8); }); it('should return error for type tags not starting with comma', () => { const buffer = Buffer.alloc(8); buffer.write('ifs'); buffer.writeUInt8(0, 3); const result = (0, parser_1.extractTypeTags)(buffer, 0); expect(result.value).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); it('should return error for non-null-terminated type tags', () => { const buffer = Buffer.alloc(8); buffer.fill(0x2c); const result = (0, parser_1.extractTypeTags)(buffer, 0); expect(result.value).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); it('should handle empty type tags', () => { const buffer = Buffer.alloc(4); buffer.write(','); buffer.writeUInt8(0, 1); const result = (0, parser_1.extractTypeTags)(buffer, 0); expect(result.error).toBeUndefined(); expect(result.value).toBe(''); expect(result.nextOffset).toBe(4); }); }); describe('extractArguments', () => { it('should extract integer arguments', () => { const buffer = Buffer.alloc(8); buffer.writeInt32BE(123, 0); buffer.writeInt32BE(456, 4); const result = (0, parser_1.extractArguments)(buffer, 0, 'ii'); expect(result.error).toBeUndefined(); expect(result.value).toEqual([123, 456]); }); it('should extract float arguments', () => { const buffer = Buffer.alloc(8); buffer.writeFloatBE(1.23, 0); buffer.writeFloatBE(4.56, 4); const result = (0, parser_1.extractArguments)(buffer, 0, 'ff'); expect(result.error).toBeUndefined(); expect(result.value).toHaveLength(2); expect(result.value[0]).toBeCloseTo(1.23); expect(result.value[1]).toBeCloseTo(4.56); }); it('should extract string arguments', () => { const buffer = Buffer.alloc(12); let offset = 0; buffer.write('hi', offset); buffer.writeUInt8(0, offset + 2); offset += 4; buffer.write('test', offset); buffer.writeUInt8(0, offset + 4); const result = (0, parser_1.extractArguments)(buffer, 0, 'ss'); expect(result.error).toBeUndefined(); expect(result.value).toEqual(['hi', 'test']); }); it('should extract blob arguments', () => { const buffer = Buffer.alloc(12); let offset = 0; buffer.writeInt32BE(4, offset); offset += 4; buffer.writeUInt8(1, offset++); buffer.writeUInt8(2, offset++); buffer.writeUInt8(3, offset++); buffer.writeUInt8(4, offset++); const result = (0, parser_1.extractArguments)(buffer, 0, 'b'); expect(result.error).toBeUndefined(); expect(result.value).toHaveLength(1); expect(Buffer.isBuffer(result.value[0])).toBe(true); expect(result.value[0]).toEqual(Buffer.from([1, 2, 3, 4])); }); it('should return error for insufficient data', () => { const buffer = Buffer.alloc(2); const result = (0, parser_1.extractArguments)(buffer, 0, 'i'); expect(result.value).toBeUndefined(); expect(result.error).toBeDefined(); expect(result.error.code).toBe(index_1.ErrorCode.INVALID_OSC_MESSAGE); }); it('should handle mixed argument types', () => { const buffer = Buffer.alloc(16); let offset = 0; buffer.writeInt32BE(42, offset); offset += 4; buffer.writeFloatBE(3.14, offset); offset += 4; buffer.write('hi', offset); buffer.writeUInt8(0, offset + 2); offset += 4; const result = (0, parser_1.extractArguments)(buffer, 0, 'ifs'); expect(result.error).toBeUndefined(); expect(result.value).toHaveLength(3); expect(result.value[0]).toBe(42); expect(result.value[1]).toBeCloseTo(3.14); expect(result.value[2]).toBe('hi'); }); }); describe('isValidOSCMessage', () => { it('should return true for potentially valid OSC message', () => { const buffer = Buffer.alloc(12); buffer.write('/test'); buffer.writeUInt8(0, 5); buffer.write(',', 8); buffer.writeUInt8(0, 9); expect((0, parser_1.isValidOSCMessage)(buffer)).toBe(true); }); it('should return false for message too short', () => { const buffer = Buffer.alloc(4); buffer.write('/hi'); expect((0, parser_1.isValidOSCMessage)(buffer)).toBe(false); }); it('should return false for message not starting with /', () => { const buffer = Buffer.alloc(12); buffer.write('test'); expect((0, parser_1.isValidOSCMessage)(buffer)).toBe(false); }); }); }); //# sourceMappingURL=parser.test.js.map