node-osc 11.2.1 → 11.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.github/workflows/nodejs.yml +1 -1
  2. package/README.md +3 -2
  3. package/agent.md +330 -0
  4. package/dist/lib/Server.js +7 -12
  5. package/dist/lib/internal/decode.js +3 -1
  6. package/dist/lib/osc.js +29 -1
  7. package/dist/test/lib/osc.js +29 -1
  8. package/dist/test/test-bundle.js +13 -12
  9. package/dist/test/test-client.js +49 -40
  10. package/dist/test/test-decode.js +35 -0
  11. package/dist/test/test-e2e.js +9 -9
  12. package/dist/test/test-encode-decode.js +96 -0
  13. package/dist/test/test-error-handling.js +14 -13
  14. package/dist/test/test-message.js +169 -119
  15. package/dist/test/test-osc-internal.js +151 -0
  16. package/dist/test/test-promises.js +71 -29
  17. package/dist/test/test-server.js +19 -16
  18. package/docs/README.md +81 -0
  19. package/examples/README.md +3 -1
  20. package/lib/Server.mjs +7 -12
  21. package/lib/internal/decode.mjs +3 -1
  22. package/lib/osc.mjs +29 -1
  23. package/package.json +2 -2
  24. package/test/test-bundle.mjs +14 -13
  25. package/test/test-client.mjs +50 -41
  26. package/test/test-decode.mjs +35 -0
  27. package/test/test-e2e.mjs +10 -10
  28. package/test/test-encode-decode.mjs +96 -0
  29. package/test/test-error-handling.mjs +15 -14
  30. package/test/test-message.mjs +171 -122
  31. package/test/test-osc-internal.mjs +151 -0
  32. package/test/test-promises.mjs +72 -30
  33. package/test/test-server.mjs +20 -17
  34. package/types/Server.d.mts.map +1 -1
  35. package/types/internal/decode.d.mts.map +1 -1
  36. package/types/osc.d.mts.map +1 -1
  37. package/dist/test/test-getPort.js +0 -20
  38. package/dist/test/util.js +0 -34
  39. package/test/test-getPort.mjs +0 -18
  40. package/test/util.mjs +0 -34
@@ -1,54 +1,67 @@
1
- import { beforeEach, test } from 'tap';
2
- import { bootstrap } from './util.mjs';
3
-
1
+ import { once } from 'node:events';
2
+ import { test } from 'tap';
4
3
  import { Server, Client, Message } from 'node-osc';
5
4
 
6
5
  function round(num) {
7
6
  return Math.round(num * 100) / 100;
8
7
  }
9
8
 
10
- beforeEach(bootstrap);
9
+ test('message: basic usage', async (t) => {
10
+ const server = new Server(0, '127.0.0.1');
11
+ await once(server, 'listening');
12
+ const client = new Client('127.0.0.1', server.port);
13
+
14
+ t.plan(1);
15
+ t.teardown(async () => {
16
+ await server.close();
17
+ await client.close();
18
+ });
11
19
 
12
- test('message: basic usage', (t) => {
13
- const oscServer = new Server(t.context.port, '127.0.0.1');
14
- const client = new Client('127.0.0.1', t.context.port);
15
20
  const m = new Message('/address');
16
21
  m.append('testing');
17
22
  m.append(123);
18
23
  m.append([456, 789]);
19
24
 
20
- oscServer.on('message', (msg) => {
25
+ server.on('message', (msg) => {
21
26
  const expected = ['/address', 'testing', 123, 456, 789];
22
27
  t.same(msg, expected, `We reveived the payload: ${msg}`);
23
- oscServer.close();
24
- t.end();
25
28
  });
26
29
 
27
- client.send(m, () => {
28
- client.close();
29
- });
30
+ client.send(m);
30
31
  });
31
32
 
32
- test('message: multiple args', (t) => {
33
- const oscServer = new Server(t.context.port, '127.0.0.1');
34
- const client = new Client('127.0.0.1', t.context.port);
33
+ test('message: multiple args', async (t) => {
34
+ const server = new Server(0, '127.0.0.1');
35
+ await once(server, 'listening');
36
+ const client = new Client('127.0.0.1', server.port);
37
+
38
+ t.plan(1);
39
+ t.teardown(async () => {
40
+ await server.close();
41
+ await client.close();
42
+ });
43
+
35
44
  const m = new Message('/address', 'testing', 123, true);
36
45
 
37
- oscServer.on('message', (msg) => {
46
+ server.on('message', (msg) => {
38
47
  const expected = ['/address', 'testing', 123, true];
39
48
  t.same(msg, expected, `We reveived the payload: ${msg}`);
40
- oscServer.close();
41
- t.end();
42
49
  });
43
50
 
44
- client.send(m, () => {
45
- client.close();
46
- });
51
+ client.send(m);
47
52
  });
48
53
 
49
- test('message: object', (t) => {
50
- const oscServer = new Server(t.context.port, '127.0.0.1');
51
- const client = new Client('127.0.0.1', t.context.port);
54
+ test('message: object', async (t) => {
55
+ const server = new Server(0, '127.0.0.1');
56
+ await once(server, 'listening');
57
+ const client = new Client('127.0.0.1', server.port);
58
+
59
+ t.plan(1);
60
+ t.teardown(async () => {
61
+ await server.close();
62
+ await client.close();
63
+ });
64
+
52
65
  const m = new Message('/address');
53
66
  m.append({
54
67
  type: 'string',
@@ -59,43 +72,51 @@ test('message: object', (t) => {
59
72
  value: 100
60
73
  });
61
74
 
62
- oscServer.on('message', (msg) => {
75
+ server.on('message', (msg) => {
63
76
  const expected = ['/address', 'test', 100];
64
77
  t.same(msg, expected, `We reveived the payload: ${msg}`);
65
- oscServer.close();
66
- t.end();
67
78
  });
68
79
 
69
- client.send(m, () => {
70
- client.close();
71
- });
80
+ client.send(m);
72
81
  });
73
82
 
74
- test('message: float', (t) => {
75
- const oscServer = new Server(t.context.port, '127.0.0.1');
76
- const client = new Client('127.0.0.1', t.context.port);
83
+ test('message: float', async (t) => {
84
+ const server = new Server(0, '127.0.0.1');
85
+ await once(server, 'listening');
86
+ const client = new Client('127.0.0.1', server.port);
87
+
88
+ t.plan(2);
89
+ t.teardown(async () => {
90
+ await server.close();
91
+ await client.close();
92
+ });
93
+
77
94
  const m = new Message('/address');
78
95
  m.append(3.14);
79
96
 
80
- oscServer.on('message', (msg) => {
97
+ server.on('message', (msg) => {
81
98
  const expected = [
82
99
  '/address',
83
100
  3.14
84
101
  ];
85
102
  t.equal(msg[0], expected[0], `We reveived the payload: ${msg}`);
86
103
  t.equal(round(msg[1]), expected[1], 'pie please');
87
- oscServer.close();
88
- t.end();
89
104
  });
90
105
 
91
- client.send(m, () => {
92
- client.close();
93
- });
106
+ client.send(m);
94
107
  });
95
108
 
96
- test('message: alias messages', (t) => {
97
- const oscServer = new Server(t.context.port, '127.0.0.1');
98
- const client = new Client('127.0.0.1', t.context.port);
109
+ test('message: alias messages', async (t) => {
110
+ const server = new Server(0, '127.0.0.1');
111
+ await once(server, 'listening');
112
+ const client = new Client('127.0.0.1', server.port);
113
+
114
+ t.plan(5);
115
+ t.teardown(async () => {
116
+ await server.close();
117
+ await client.close();
118
+ });
119
+
99
120
  const m = new Message('/address');
100
121
  m.append({
101
122
  type: 'i',
@@ -106,7 +127,7 @@ test('message: alias messages', (t) => {
106
127
  value: 3.14
107
128
  });
108
129
 
109
- oscServer.on('message', (msg) => {
130
+ server.on('message', (msg) => {
110
131
  const expected = [
111
132
  '/address',
112
133
  123,
@@ -117,39 +138,47 @@ test('message: alias messages', (t) => {
117
138
  t.ok(Number.isInteger(msg[1]), 'the first value is an int');
118
139
  t.equal(round(msg[2]), expected[2], 'pie please');
119
140
  t.ok(msg[2] % 1 !== 0, 'the second value is a float');
120
- oscServer.close();
121
- t.end();
122
141
  });
123
142
 
124
- client.send(m, () => {
125
- client.close();
126
- });
143
+ client.send(m);
127
144
  });
128
145
 
129
- test('message: boolean', (t) => {
130
- const oscServer = new Server(t.context.port, '127.0.0.1');
131
- const client = new Client('127.0.0.1', t.context.port);
146
+ test('message: boolean', async (t) => {
147
+ const server = new Server(0, '127.0.0.1');
148
+ await once(server, 'listening');
149
+
150
+ t.plan(1);
151
+ t.teardown(async () => {
152
+ await server.close();
153
+ await client.close();
154
+ });
155
+
156
+ const client = new Client('127.0.0.1', server.port);
132
157
  const m = new Message('/address');
133
158
  m.append(true);
134
159
 
135
- oscServer.on('message', (msg) => {
160
+ server.on('message', (msg) => {
136
161
  const expected = [
137
162
  '/address',
138
163
  true
139
164
  ];
140
165
  t.same(msg, expected, `We reveived the payload: ${msg}`);
141
- oscServer.close();
142
- t.end();
143
166
  });
144
167
 
145
- client.send(m, () => {
146
- client.close();
147
- });
168
+ client.send(m);
148
169
  });
149
170
 
150
- test('message: blob', (t) => {
151
- const oscServer = new Server(t.context.port, '127.0.0.1');
152
- const client = new Client('127.0.0.1', t.context.port);
171
+ test('message: blob', async (t) => {
172
+ const server = new Server(0, '127.0.0.1');
173
+ await once(server, 'listening');
174
+ const client = new Client('127.0.0.1', server.port);
175
+
176
+ t.plan(1);
177
+ t.teardown(async () => {
178
+ await server.close();
179
+ await client.close();
180
+ });
181
+
153
182
  const m = new Message('/address');
154
183
  const buf = Buffer.from('test');
155
184
  m.append({
@@ -157,42 +186,42 @@ test('message: blob', (t) => {
157
186
  value: buf
158
187
  });
159
188
 
160
- oscServer.on('message', (msg) => {
189
+ server.on('message', (msg) => {
161
190
  const expected = [
162
191
  '/address',
163
192
  buf
164
193
  ];
165
194
  t.same(msg, expected, `We reveived the payload: ${msg}`);
166
- oscServer.close();
167
- t.end();
168
195
  });
169
196
 
170
- client.send(m, () => {
171
- client.close();
172
- });
197
+ client.send(m);
173
198
  });
174
199
 
175
- test('message: Buffer as blob', (t) => {
176
- const oscServer = new Server(t.context.port, '127.0.0.1');
177
- const client = new Client('127.0.0.1', t.context.port);
200
+ test('message: Buffer as blob', async (t) => {
201
+ const server = new Server(0, '127.0.0.1');
202
+ await once(server, 'listening');
203
+ const client = new Client('127.0.0.1', server.port);
204
+
205
+ t.plan(1);
206
+ t.teardown(async () => {
207
+ await server.close();
208
+ await client.close();
209
+ });
210
+
178
211
  const m = new Message('/address');
179
212
  const buf = Buffer.from('test buffer data');
180
213
  // Directly append Buffer without wrapping in object
181
214
  m.append(buf);
182
215
 
183
- oscServer.on('message', (msg) => {
216
+ server.on('message', (msg) => {
184
217
  const expected = [
185
218
  '/address',
186
219
  buf
187
220
  ];
188
221
  t.same(msg, expected, `We received the buffer payload: ${msg}`);
189
- oscServer.close();
190
- t.end();
191
222
  });
192
223
 
193
- client.send(m, () => {
194
- client.close();
195
- });
224
+ client.send(m);
196
225
  });
197
226
 
198
227
  // test('message: timetag', (t) => {
@@ -214,9 +243,17 @@ test('message: Buffer as blob', (t) => {
214
243
  // });
215
244
  // });
216
245
 
217
- test('message: Buffer with multiple arguments', (t) => {
218
- const oscServer = new Server(t.context.port, '127.0.0.1');
219
- const client = new Client('127.0.0.1', t.context.port);
246
+ test('message: Buffer with multiple arguments', async (t) => {
247
+ const server = new Server(0, '127.0.0.1');
248
+ await once(server, 'listening');
249
+ const client = new Client('127.0.0.1', server.port);
250
+
251
+ t.plan(6);
252
+ t.teardown(async () => {
253
+ await server.close();
254
+ await client.close();
255
+ });
256
+
220
257
  const m = new Message('/address');
221
258
  const buf1 = Buffer.from('first');
222
259
  const buf2 = Buffer.from('second');
@@ -227,29 +264,33 @@ test('message: Buffer with multiple arguments', (t) => {
227
264
  m.append(3.14);
228
265
  m.append(buf2);
229
266
 
230
- oscServer.on('message', (msg) => {
267
+ server.on('message', (msg) => {
231
268
  t.equal(msg[0], '/address', 'Address matches');
232
269
  t.equal(msg[1], 'string', 'String matches');
233
270
  t.equal(msg[2], 42, 'Integer matches');
234
271
  t.same(msg[3], buf1, 'First buffer matches');
235
272
  t.equal(round(msg[4]), 3.14, 'Float matches');
236
- t.same(msg[5], buf2, 'Second buffer matches');
237
- oscServer.close();
238
- t.end();
273
+ t.same(msg[5], buf2, 'Second buffer matches')
239
274
  });
240
275
 
241
- client.send(m, () => {
242
- client.close();
243
- });
276
+ client.send(m);
244
277
  });
245
278
 
246
- test('message: Buffer in constructor', (t) => {
247
- const oscServer = new Server(t.context.port, '127.0.0.1');
248
- const client = new Client('127.0.0.1', t.context.port);
279
+ test('message: Buffer in constructor', async (t) => {
280
+ const server = new Server(0, '127.0.0.1');
281
+ await once(server, 'listening');
282
+ const client = new Client('127.0.0.1', server.port);
283
+
284
+ t.plan(1);
285
+ t.teardown(async () => {
286
+ await server.close();
287
+ await client.close();
288
+ });
289
+
249
290
  const buf = Buffer.from('constructor buffer');
250
291
  const m = new Message('/address', 'test', buf, 123);
251
292
 
252
- oscServer.on('message', (msg) => {
293
+ server.on('message', (msg) => {
253
294
  const expected = [
254
295
  '/address',
255
296
  'test',
@@ -257,25 +298,29 @@ test('message: Buffer in constructor', (t) => {
257
298
  123
258
299
  ];
259
300
  t.same(msg, expected, `We received the constructor buffer payload: ${msg}`);
260
- oscServer.close();
261
- t.end();
262
301
  });
263
302
 
264
- client.send(m, () => {
265
- client.close();
266
- });
303
+ client.send(m);
267
304
  });
268
305
 
269
- test('message: Buffer in array', (t) => {
270
- const oscServer = new Server(t.context.port, '127.0.0.1');
271
- const client = new Client('127.0.0.1', t.context.port);
306
+ test('message: Buffer in array', async (t) => {
307
+ const server = new Server(0, '127.0.0.1');
308
+ await once(server, 'listening');
309
+ const client = new Client('127.0.0.1', server.port);
310
+
311
+ t.plan(1);
312
+ t.teardown(async () => {
313
+ await server.close();
314
+ await client.close();
315
+ });
316
+
272
317
  const m = new Message('/address');
273
318
  const buf1 = Buffer.from('array1');
274
319
  const buf2 = Buffer.from('array2');
275
320
 
276
321
  m.append([buf1, 'string', buf2, 456]);
277
322
 
278
- oscServer.on('message', (msg) => {
323
+ server.on('message', (msg) => {
279
324
  const expected = [
280
325
  '/address',
281
326
  buf1,
@@ -284,58 +329,62 @@ test('message: Buffer in array', (t) => {
284
329
  456
285
330
  ];
286
331
  t.same(msg, expected, `We received the array with buffers: ${msg}`);
287
- oscServer.close();
288
- t.end();
289
332
  });
290
333
 
291
- client.send(m, () => {
292
- client.close();
293
- });
334
+ client.send(m);
294
335
  });
295
336
 
296
- test('message: empty Buffer', (t) => {
297
- const oscServer = new Server(t.context.port, '127.0.0.1');
298
- const client = new Client('127.0.0.1', t.context.port);
337
+ test('message: empty Buffer', async (t) => {
338
+ const server = new Server(0, '127.0.0.1');
339
+ await once(server, 'listening');
340
+ const client = new Client('127.0.0.1', server.port);
341
+
342
+ t.plan(1);
343
+ t.teardown(async () => {
344
+ await server.close();
345
+ await client.close();
346
+ });
347
+
299
348
  const m = new Message('/address');
300
349
  const buf = Buffer.from('');
301
350
 
302
351
  m.append(buf);
303
352
 
304
- oscServer.on('message', (msg) => {
353
+ server.on('message', (msg) => {
305
354
  const expected = [
306
355
  '/address',
307
356
  buf
308
357
  ];
309
358
  t.same(msg, expected, `We received the empty buffer: ${msg}`);
310
- oscServer.close();
311
- t.end();
312
359
  });
313
360
 
314
- client.send(m, () => {
315
- client.close();
316
- });
361
+ client.send(m);
317
362
  });
318
363
 
319
- test('message: large Buffer', (t) => {
320
- const oscServer = new Server(t.context.port, '127.0.0.1');
321
- const client = new Client('127.0.0.1', t.context.port);
364
+ test('message: large Buffer', async (t) => {
365
+ const server = new Server(0, '127.0.0.1');
366
+ await once(server, 'listening');
367
+ const client = new Client('127.0.0.1', server.port);
368
+
369
+ t.plan(4);
370
+ t.teardown(async () => {
371
+ await server.close();
372
+ await client.close();
373
+ });
374
+
322
375
  const m = new Message('/address');
323
376
  const buf = Buffer.alloc(1024, 'x');
324
377
 
325
378
  m.append(buf);
326
379
 
327
- oscServer.on('message', (msg) => {
380
+ server.on('message', (msg) => {
328
381
  t.equal(msg[0], '/address', 'Address matches');
329
382
  t.ok(Buffer.isBuffer(msg[1]), 'Second element is a Buffer');
330
383
  t.equal(msg[1].length, 1024, 'Buffer size matches');
331
384
  t.same(msg[1], buf, 'Buffer content matches');
332
- oscServer.close();
333
- t.end();
334
385
  });
335
386
 
336
- client.send(m, () => {
337
- client.close();
338
- });
387
+ client.send(m);
339
388
  });
340
389
 
341
390
  test('message: error', (t) => {
@@ -23,6 +23,46 @@ test('osc: timetag encoding with non-number value', (t) => {
23
23
  t.end();
24
24
  });
25
25
 
26
+ test('osc: timetag encoding with zero value', (t) => {
27
+ const bundle = {
28
+ oscType: 'bundle',
29
+ timetag: 0,
30
+ elements: [
31
+ {
32
+ oscType: 'message',
33
+ address: '/test',
34
+ args: []
35
+ }
36
+ ]
37
+ };
38
+
39
+ const buffer = encode(bundle);
40
+ const decoded = decode(buffer);
41
+
42
+ t.equal(decoded.timetag, 0, 'should encode 0 as immediate execution');
43
+ t.end();
44
+ });
45
+
46
+ test('osc: timetag encoding with numeric epoch value', (t) => {
47
+ const bundle = {
48
+ oscType: 'bundle',
49
+ timetag: 42,
50
+ elements: [
51
+ {
52
+ oscType: 'message',
53
+ address: '/test',
54
+ args: []
55
+ }
56
+ ]
57
+ };
58
+
59
+ const buffer = encode(bundle);
60
+ const decoded = decode(buffer);
61
+
62
+ t.equal(decoded.timetag, 42, 'should preserve numeric timetag values');
63
+ t.end();
64
+ });
65
+
26
66
  test('osc: timetag with immediate execution values', (t) => {
27
67
  // Test readTimeTag with seconds === 0 && fraction === 1
28
68
  const bundle = {
@@ -765,6 +805,117 @@ test('osc: explicit double type name', (t) => {
765
805
  t.end();
766
806
  });
767
807
 
808
+ test('osc: malformed packet with missing string terminator', (t) => {
809
+ const buffer = Buffer.from('/test', 'utf8');
810
+
811
+ t.throws(() => {
812
+ decode(buffer);
813
+ }, /Malformed Packet: Missing null terminator for string/, 'should throw on unterminated string');
814
+ t.end();
815
+ });
816
+
817
+ test('osc: malformed packet with truncated int32 argument', (t) => {
818
+ const address = Buffer.from('/i\0\0', 'ascii');
819
+ const typeTags = Buffer.from(',i\0\0', 'ascii');
820
+ const truncated = Buffer.from([0x00, 0x01]);
821
+ const buffer = Buffer.concat([address, typeTags, truncated]);
822
+
823
+ t.throws(() => {
824
+ decode(buffer);
825
+ }, /Malformed Packet: Not enough bytes for int32/, 'should throw on truncated int32');
826
+ t.end();
827
+ });
828
+
829
+ test('osc: malformed packet with truncated float32 argument', (t) => {
830
+ const address = Buffer.from('/f\0\0', 'ascii');
831
+ const typeTags = Buffer.from(',f\0\0', 'ascii');
832
+ const truncated = Buffer.from([0x3f, 0x80, 0x00]);
833
+ const buffer = Buffer.concat([address, typeTags, truncated]);
834
+
835
+ t.throws(() => {
836
+ decode(buffer);
837
+ }, /Malformed Packet: Not enough bytes for float32/, 'should throw on truncated float32');
838
+ t.end();
839
+ });
840
+
841
+ test('osc: malformed packet with invalid blob length', (t) => {
842
+ const address = Buffer.from('/b\0\0', 'ascii');
843
+ const typeTags = Buffer.from(',b\0\0', 'ascii');
844
+ const length = Buffer.alloc(4);
845
+ length.writeInt32BE(-1, 0);
846
+ const buffer = Buffer.concat([address, typeTags, length]);
847
+
848
+ t.throws(() => {
849
+ decode(buffer);
850
+ }, /Malformed Packet: Invalid blob length/, 'should throw on negative blob length');
851
+ t.end();
852
+ });
853
+
854
+ test('osc: malformed packet with truncated blob data', (t) => {
855
+ const address = Buffer.from('/b\0\0', 'ascii');
856
+ const typeTags = Buffer.from(',b\0\0', 'ascii');
857
+ const length = Buffer.alloc(4);
858
+ length.writeInt32BE(4, 0);
859
+ const data = Buffer.from([0x01, 0x02]);
860
+ const buffer = Buffer.concat([address, typeTags, length, data]);
861
+
862
+ t.throws(() => {
863
+ decode(buffer);
864
+ }, /Malformed Packet: Not enough bytes for blob/, 'should throw on truncated blob data');
865
+ t.end();
866
+ });
867
+
868
+ test('osc: malformed packet with missing blob padding', (t) => {
869
+ const address = Buffer.from('/b\0\0', 'ascii');
870
+ const typeTags = Buffer.from(',b\0\0', 'ascii');
871
+ const length = Buffer.alloc(4);
872
+ length.writeInt32BE(3, 0);
873
+ const data = Buffer.from([0x01, 0x02, 0x03]);
874
+ const buffer = Buffer.concat([address, typeTags, length, data]);
875
+
876
+ t.throws(() => {
877
+ decode(buffer);
878
+ }, /Malformed Packet: Not enough bytes for blob padding/, 'should throw on missing blob padding');
879
+ t.end();
880
+ });
881
+
882
+ test('osc: malformed bundle with truncated timetag', (t) => {
883
+ const bundleHeader = Buffer.from('#bundle\0', 'ascii');
884
+ const timetag = Buffer.alloc(4);
885
+ const buffer = Buffer.concat([bundleHeader, timetag]);
886
+
887
+ t.throws(() => {
888
+ decode(buffer);
889
+ }, /Malformed Packet: Not enough bytes for timetag/, 'should throw on truncated timetag');
890
+ t.end();
891
+ });
892
+
893
+ test('osc: malformed bundle with invalid element size', (t) => {
894
+ const bundleHeader = Buffer.from('#bundle\0', 'ascii');
895
+ const timetag = Buffer.alloc(8);
896
+ const size = Buffer.alloc(4);
897
+ size.writeInt32BE(0, 0);
898
+ const buffer = Buffer.concat([bundleHeader, timetag, size]);
899
+
900
+ t.throws(() => {
901
+ decode(buffer);
902
+ }, /Malformed Packet/, 'should throw on invalid bundle element size');
903
+ t.end();
904
+ });
905
+
906
+ test('osc: malformed bundle with oversized element size', (t) => {
907
+ const bundleHeader = Buffer.from('#bundle\0', 'ascii');
908
+ const timetag = Buffer.alloc(8);
909
+ const size = Buffer.alloc(4);
910
+ size.writeInt32BE(12, 0);
911
+ const buffer = Buffer.concat([bundleHeader, timetag, size, Buffer.from([0x01, 0x02])]);
912
+
913
+ t.throws(() => {
914
+ decode(buffer);
915
+ }, /Malformed Packet/, 'should throw on oversized bundle element size');
916
+ t.end();
917
+ });
918
+
768
919
  test('osc: blob padding when length is multiple of 4', (t) => {
769
920
  // Test writeBlob line 52: padding === 4 branch (should use 0)
770
921
  const message = {