n8n/packages/@n8n/syslog-client/test/formats.test.ts

286 lines
7.6 KiB
TypeScript

import { SyslogClient, Transport } from '../src';
import {
awaitUdpMsg,
constructRfc5424Regex,
constructSyslogRegex,
startTestServers,
stopTestServers,
SYSLOG_UDP_PORT,
} from './setup';
beforeAll(async () => {
await startTestServers();
});
afterAll(() => {
stopTestServers();
});
describe('SyslogClient - Message Formats', () => {
describe('RFC 3164 (BSD syslog)', () => {
it('should send RFC 3164 format by default', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
await client.log('RFC 3164 test');
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructSyslogRegex(134, hostname, 'RFC 3164 test'));
client.close();
});
it('should send RFC 3164 format when explicitly enabled', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
rfc3164: true,
});
await client.log('RFC 3164 explicit');
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructSyslogRegex(134, hostname, 'RFC 3164 explicit'));
client.close();
});
it('should send back-dated RFC 3164 messages', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
const backdate = new Date(2017, 2, 1);
await client.log('Back-dated test', { timestamp: backdate });
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructSyslogRegex(134, hostname, 'Back-dated test', backdate));
client.close();
});
it('should handle messages with custom options', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
await client.log('Custom options', {
rfc3164: true,
msgid: '12345', // msgid is ignored in RFC 3164
});
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructSyslogRegex(134, hostname, 'Custom options'));
client.close();
});
});
describe('RFC 5424 (modern syslog)', () => {
it('should send RFC 5424 format when enabled', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
rfc3164: false,
});
await client.log('RFC 5424 test');
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructRfc5424Regex(134, hostname, 'RFC 5424 test', '-'));
client.close();
});
it('should use default msgid when not provided', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
await client.log('Default msgid', { rfc3164: false });
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructRfc5424Regex(134, hostname, 'Default msgid', '-'));
client.close();
});
it('should use custom msgid when provided', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
await client.log('Custom msgid', {
rfc3164: false,
msgid: '98765',
});
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructRfc5424Regex(134, hostname, 'Custom msgid', '98765'));
client.close();
});
it('should accept msgid up to 32 characters (RFC 5424 limit)', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
const maxLengthMsgid = '550e8400e29b41d4a716446655440000'; // 32 chars (UUID without hyphens)
await client.log('Max length msgid', {
rfc3164: false,
msgid: maxLengthMsgid,
});
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructRfc5424Regex(134, hostname, 'Max length msgid', maxLengthMsgid));
client.close();
});
it('should reject msgid longer than 32 characters (RFC 5424 limit)', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
const tooLongMsgid = '550e8400-e29b-41d4-a716-446655440000'; // 36 chars (UUID with hyphens)
await expect(
client.log('Too long msgid', {
rfc3164: false,
msgid: tooLongMsgid,
}),
).rejects.toThrow();
client.close();
});
it('should send back-dated RFC 5424 messages', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
const backdate = new Date(2017, 2, 1);
await client.log('Back-dated RFC 5424', {
rfc3164: false,
msgid: '98765',
timestamp: backdate,
});
const msg = await awaitUdpMsg();
expect(msg).toMatch(
constructRfc5424Regex(134, hostname, 'Back-dated RFC 5424', '98765', backdate),
);
client.close();
});
it('should include process ID in RFC 5424 messages', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
rfc3164: false,
});
await client.log('Process ID test');
const msg = await awaitUdpMsg();
// Check that message contains a process ID (numeric)
expect(msg).toMatch(/\d+ - - Process ID test/);
client.close();
});
});
describe('Format switching', () => {
it('should allow switching format per message', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
rfc3164: true, // Default to RFC 3164
});
// Send RFC 3164 message (default)
await client.log('Message 1');
const msg1 = await awaitUdpMsg();
expect(msg1).toMatch(constructSyslogRegex(134, hostname, 'Message 1'));
// Send RFC 5424 message (override)
await client.log('Message 2', { rfc3164: false });
const msg2 = await awaitUdpMsg();
expect(msg2).toMatch(constructRfc5424Regex(134, hostname, 'Message 2', '-'));
// Send RFC 3164 message again (back to default)
await client.log('Message 3');
const msg3 = await awaitUdpMsg();
expect(msg3).toMatch(constructSyslogRegex(134, hostname, 'Message 3'));
client.close();
});
});
describe('Message content', () => {
it('should preserve newlines in message', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
const messageWithNewline = 'Message with\nnewline';
await client.log(messageWithNewline);
const msg = await awaitUdpMsg();
expect(msg).toContain(messageWithNewline);
client.close();
});
it('should handle empty messages', async () => {
const hostname = 'testhostname';
const client = new SyslogClient('127.0.0.1', {
port: SYSLOG_UDP_PORT,
syslogHostname: hostname,
transport: Transport.Udp,
});
await client.log('');
const msg = await awaitUdpMsg();
expect(msg).toMatch(constructSyslogRegex(134, hostname, ''));
client.close();
});
});
});