/liblo-0.26/src/testlo.c
C | 1193 lines | 971 code | 159 blank | 63 comment | 335 complexity | 9d4d96a30c22302d6bb96bec1d07ff31 MD5 | raw file
Possible License(s): LGPL-2.1
1/*
2 * Copyright (C) 2004 Steve Harris
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * $Id$
15 */
16
17/*
18 * This is some testcase code - it exercises the internals of liblo, so its not
19 * a good example to learn from, see examples/ for example code
20 */
21
22#include <math.h>
23#include <float.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#ifdef _MSC_VER
29#define snprintf _snprintf
30#else
31#include <unistd.h>
32#endif
33
34#include "lo_types_internal.h"
35#include "lo_internal.h"
36#include "lo/lo.h"
37#include "config.h"
38
39#ifdef WIN32
40#define PATHDELIM "\\"
41#else
42#define PATHDELIM "/"
43#endif
44
45#ifndef MSG_NOSIGNAL
46#define MSG_NOSIGNAL 0
47#endif
48
49#define TEST(cond) if (!(cond)) { fprintf(stderr, "FAILED " #cond \
50 " at %s:%d\n", __FILE__, __LINE__); \
51 exit(1); } \
52 else { printf("passed " #cond "\n"); }
53
54union end_test32 {
55 uint32_t i;
56 char c[4];
57};
58
59union end_test64 {
60 uint64_t i;
61 char c[8];
62};
63
64static int done = 0;
65static int bundle_count = 0;
66static int pattern_count = 0;
67static int reply_count = 0;
68static int subtest_count = 0;
69static int subtest_reply_count = 0;
70static int error_okay = 0;
71
72char testdata[5] = "ABCDE";
73
74static int jitter_count = 0;
75static float jitter_total = 0.0f;
76static float jitter_max = 0.0f;
77static float jitter_min = 1000.0f;
78
79void exitcheck(void);
80void test_deserialise(void);
81void test_validation(lo_address a);
82void test_multicast(lo_server_thread st);
83void error(int num, const char *m, const char *path);
84void rep_error(int num, const char *m, const char *path);
85
86int generic_handler(const char *path, const char *types, lo_arg **argv,
87 int argc, lo_message data, void *user_data);
88
89int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
90 lo_message data, void *user_data);
91
92int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
93 lo_message data, void *user_data);
94
95int lots_handler(const char *path, const char *types, lo_arg **argv, int argc,
96 lo_message data, void *user_data);
97
98int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc,
99 lo_message data, void *user_data);
100
101int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc,
102 lo_message data, void *user_data);
103
104int timestamp_handler(const char *path, const char *types, lo_arg **argv,
105 int argc, lo_message data, void *user_data);
106
107int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc,
108 lo_message data, void *user_data);
109
110int pattern_handler(const char *path, const char *types, lo_arg **argv,
111 int argc, lo_message data, void *user_data);
112
113int subtest_handler(const char *path, const char *types, lo_arg **argv,
114 int argc, lo_message data, void *user_data);
115
116int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
117 int argc, lo_message data, void *user_data);
118
119int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
120 lo_message data, void *user_data);
121
122int test_varargs(lo_address a, const char *path, const char *types, ...);
123
124int main()
125{
126 lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
127 lo_server_thread st, sta, stb;
128 lo_server s = lo_server_new(NULL, error);
129 lo_bundle b;
130 lo_message m1, m2;
131 char *server_url, *path, *protocol, *host, *port;
132 const char *host2, *port2;
133 lo_address a;
134 uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
135 union end_test32 et32;
136 union end_test64 et64;
137 lo_timetag tt = {0x1, 0x80000000}, sched;
138 int count;
139 int proto;
140 char cmd[256];
141
142 test_deserialise();
143
144 sta = lo_server_thread_new("7591", error);
145 stb = lo_server_thread_new("7591", rep_error);
146 if (stb) {
147 fprintf(stderr, "FAILED: create bad server thread object!\n");
148 exit(1);
149 }
150 lo_server_thread_free(sta);
151
152 /* leak check */
153 st = lo_server_thread_new(NULL, error);
154 lo_server_thread_start(st);
155#ifdef WIN32
156 Sleep(4);
157#else
158 usleep(4000);
159#endif
160 lo_server_thread_stop(st);
161 lo_server_thread_free(st);
162 st = lo_server_thread_new(NULL, error);
163 lo_server_thread_start(st);
164 lo_server_thread_stop(st);
165 lo_server_thread_free(st);
166 st = lo_server_thread_new(NULL, error);
167 lo_server_thread_free(st);
168 st = lo_server_thread_new(NULL, error);
169 lo_server_thread_free(st);
170 st = lo_server_thread_new(NULL, error);
171
172 a = lo_address_new_from_url("osc://localhost/");
173 TEST(a != NULL);
174 lo_address_free(a);
175
176 a = lo_address_new_from_url("osc.://localhost/");
177 TEST(a == NULL);
178
179
180 atexit(exitcheck);
181
182 printf("type tests\n");
183 TEST(sizeof(float) == sizeof(int32_t));
184 TEST(sizeof(double) == sizeof(int64_t));
185
186 et32.i = 0x23242526U;
187 et32.i = lo_htoo32(et32.i);
188 if (et32.c[0] != 0x23 || et32.c[1] != 0x24 || et32.c[2] != 0x25 ||
189 et32.c[3] != 0x26) {
190 fprintf(stderr, "failed 32bit endian conversion test\n");
191 fprintf(stderr, "0x23242526 -> %X\n", et32.i);
192 exit(1);
193 } else {
194 printf("passed 32bit endian conversion test\n");
195 }
196
197 et64.i = 0x232425262728292AULL;
198 et64.i = lo_htoo64(et64.i);
199 if (et64.c[0] != 0x23 || et64.c[1] != 0x24 || et64.c[2] != 0x25 ||
200 et64.c[3] != 0x26 || et64.c[4] != 0x27 || et64.c[5] != 0x28 ||
201 et64.c[6] != 0x29 || et64.c[7] != 0x2A) {
202 fprintf(stderr, "failed 64bit endian conversion\n");
203 fprintf(stderr, "0x232425262728292A -> %llX\n", (long long unsigned int)et64.i);
204 exit(1);
205 } else {
206 printf("passed 64bit endian conversion\n");
207 }
208 printf("\n");
209
210 /* OSC URL tests */
211 path = lo_url_get_path("osc.udp://localhost:9999/a/path/is/here");
212 if (strcmp(path, "/a/path/is/here")) {
213 printf("failed lo_url_get_path() test1\n");
214 printf("'%s' != '/a/path/is/here'\n", path);
215 exit(1);
216 } else {
217 printf("passed lo_url_get_path() test1\n");
218 }
219 free(path);
220
221 protocol = lo_url_get_protocol("osc.udp://localhost:9999/a/path/is/here");
222 if (strcmp(protocol, "udp")) {
223 printf("failed lo_url_get_protocol() test1\n");
224 printf("'%s' != 'udp'\n", protocol);
225 exit(1);
226 } else {
227 printf("passed lo_url_get_protocol() test1\n");
228 }
229 free(protocol);
230
231 protocol = lo_url_get_protocol("osc.tcp://localhost:9999/a/path/is/here");
232 if (strcmp(protocol, "tcp")) {
233 printf("failed lo_url_get_protocol() test2\n");
234 printf("'%s' != 'tcp'\n", protocol);
235 exit(1);
236 } else {
237 printf("passed lo_url_get_protocol() test2\n");
238 }
239 free(protocol);
240
241 protocol = lo_url_get_protocol("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
242 if (strcmp(protocol, "udp")) {
243 printf("failed lo_url_get_protocol() test1 (IPv6)\n");
244 printf("'%s' != 'udp'\n", protocol);
245 exit(1);
246 } else {
247 printf("passed lo_url_get_protocol() test1 (IPv6)\n");
248 }
249 free(protocol);
250
251 proto = lo_url_get_protocol_id("osc.udp://localhost:9999/a/path/is/here");
252 if (proto != LO_UDP) {
253 printf("failed lo_url_get_protocol_id() test1\n");
254 printf("'%d' != LO_UDP\n", proto);
255 exit(1);
256 } else {
257 printf("passed lo_url_get_protocol_id() test1\n");
258 }
259
260 proto = lo_url_get_protocol_id("osc.tcp://localhost:9999/a/path/is/here");
261 if (proto != LO_TCP) {
262 printf("failed lo_url_get_protocol_id() test2\n");
263 printf("'%d' != LO_TCP\n", proto);
264 exit(1);
265 } else {
266 printf("passed lo_url_get_protocol_id() test2\n");
267 }
268
269 proto = lo_url_get_protocol_id("osc.invalid://localhost:9999/a/path/is/here");
270 if (proto != -1) {
271 printf("failed lo_url_get_protocol_id() test3\n");
272 printf("'%d' != -1\n", proto);
273 exit(1);
274 } else {
275 printf("passed lo_url_get_protocol_id() test3\n");
276 }
277
278 proto = lo_url_get_protocol_id("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
279 if (proto != LO_UDP) {
280 printf("failed lo_url_get_protocol_id() test1 (IPv6)\n");
281 printf("'%d' != LO_UDP\n", proto);
282 exit(1);
283 } else {
284 printf("passed lo_url_get_protocol_id() test1 (IPv6)\n");
285 }
286
287 host = lo_url_get_hostname("osc.udp://foo.example.com:9999/a/path/is/here");
288 if (strcmp(host, "foo.example.com")) {
289 printf("failed lo_url_get_hostname() test1\n");
290 printf("'%s' != 'foo.example.com'\n", host);
291 exit(1);
292 } else {
293 printf("passed lo_url_get_hostname() test1\n");
294 }
295 free(host);
296
297 host = lo_url_get_hostname("osc.udp://[0000::::0001]:9999/a/path/is/here");
298 if (strcmp(host, "0000::::0001")) {
299 printf("failed lo_url_get_hostname() test2 (IPv6)\n");
300 printf("'%s' != '0000::::0001'\n", host);
301 exit(1);
302 } else {
303 printf("passed lo_url_get_hostname() test2 (IPv6)\n");
304 }
305 free(host);
306
307 port = lo_url_get_port("osc.udp://localhost:9999/a/path/is/here");
308 if (strcmp(port, "9999")) {
309 printf("failed lo_url_get_port() test1\n");
310 printf("'%s' != '9999'\n", port);
311 exit(1);
312 } else {
313 printf("passed lo_url_get_port() test1\n");
314 }
315 free(port);
316
317 port = lo_url_get_port("osc.udp://[::ffff:127.0.0.1]:9999/a/path/is/here");
318 if (strcmp(port, "9999")) {
319 printf("failed lo_url_get_port() test1 (IPv6)\n");
320 printf("'%s' != '9999'\n", port);
321 exit(1);
322 } else {
323 printf("passed lo_url_get_port() test1 (IPv6)\n");
324 }
325 free(port);
326 printf("\n");
327
328
329
330
331
332 a = lo_address_new_from_url("osc.tcp://foo.example.com:9999/");
333 host2 = lo_address_get_hostname(a);
334 if (strcmp(host2, "foo.example.com")) {
335 printf("failed lo_address_get_hostname() test\n");
336 printf("'%s' != 'foo.example.com'\n", host2);
337 exit(1);
338 } else {
339 printf("passed lo_address_get_hostname() test\n");
340 }
341
342 port2 = lo_address_get_port(a);
343 if (strcmp(port2, "9999")) {
344 printf("failed lo_address_get_port() test\n");
345 printf("'%s' != '9999'\n", port2);
346 exit(1);
347 } else {
348 printf("passed lo_address_get_port() test\n");
349 }
350
351 proto = lo_address_get_protocol(a);
352 if (proto != LO_TCP) {
353 printf("failed lo_address_get_protocol() test\n");
354 printf("'%d' != '%d'\n", proto, LO_TCP);
355 exit(1);
356 } else {
357 printf("passed lo_address_get_protocol() test\n");
358 }
359
360 server_url = lo_address_get_url(a);
361 if (strcmp(server_url, "osc.tcp://foo.example.com:9999/")) {
362 printf("failed lo_address_get_url() test\n");
363 printf("'%s' != '%s'\n", server_url, "osc.tcp://foo.example.com:9999/");
364 exit(1);
365 } else {
366 printf("passed lo_address_get_url() test\n");
367 }
368 free(server_url);
369 lo_address_free( a );
370 printf("\n");
371
372
373 /* Test blod sizes */
374 if (lo_blob_datasize(btest) != 5 || lo_blobsize(btest) != 12) {
375 printf("blob is %d (%d) bytes long, should be 5 (12)\n",
376 lo_blob_datasize(btest), lo_blobsize(btest));
377 lo_arg_pp(LO_BLOB, btest);
378 printf(" <- blob\n");
379 exit(1);
380 }
381
382
383
384 /* Server method handler tests */
385 server_url = lo_server_thread_get_url(st);
386 a = lo_address_new_from_url(server_url);
387 printf("Server URL: %s\n", server_url);
388 free(server_url);
389
390 /* add method that will match the path /foo/bar, with two numbers, coerced
391 * to float and int */
392
393 lo_server_thread_add_method(st, "/foo/bar", "fi", foo_handler, lo_server_thread_get_server(st));
394
395 lo_server_thread_add_method(st, "/reply", "s", reply_handler, NULL);
396
397 lo_server_thread_add_method(st, "/lotsofformats", "fisbmhtdSccTFNI",
398 lots_handler, NULL);
399
400 lo_server_thread_add_method(st, "/coerce", "dfhiSs",
401 coerce_handler, NULL);
402
403 lo_server_thread_add_method(st, "/bundle", NULL,
404 bundle_handler, NULL);
405 lo_server_thread_add_method(st, "/timestamp", NULL,
406 timestamp_handler, NULL);
407 lo_server_thread_add_method(st, "/jitter", "ti",
408 jitter_handler, NULL);
409
410 lo_server_thread_add_method(st, "/pattern/foo", NULL,
411 pattern_handler, "foo");
412 lo_server_thread_add_method(st, "/pattern/bar", NULL,
413 pattern_handler, "bar");
414 lo_server_thread_add_method(st, "/pattern/baz", NULL,
415 pattern_handler, "baz");
416
417 lo_server_thread_add_method(st, "/subtest", "i",
418 subtest_handler, st);
419
420 lo_server_thread_add_method(st, "/subtest-reply", "i",
421 subtest_reply_handler, NULL);
422
423 /* add method that will match any path and args */
424 lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL);
425
426 /* add method that will match the path /quit with no args */
427 lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL);
428
429 /* check that the thread restarts */
430 lo_server_thread_start(st);
431 lo_server_thread_stop(st);
432 lo_server_thread_start(st);
433
434 if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
435 printf("OSC error A %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
436 exit(1);
437 }
438
439 if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
440 printf("OSC error B %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
441 exit(1);
442 }
443
444 test_validation(a);
445 test_multicast(st);
446
447 lo_send(a, "/", "i", 242);
448 lo_send(a, "/pattern/", "i", 243);
449
450#ifndef _MSC_VER /* MS compiler refuses to compile this case */
451 lo_send(a, "/bar", "ff", 0.12345678f, 1.0/0.0);
452#endif
453 lo_send(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
454 btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
455 'X', 'Y');
456 lo_send(a, "/coerce", "fdihsS", 0.1f, 0.2, 123, 124LL, "aaa", "bbb");
457 lo_send(a, "/coerce", "ffffss", 0.1f, 0.2f, 123.0, 124.0, "aaa", "bbb");
458 lo_send(a, "/coerce", "ddddSS", 0.1, 0.2, 123.0, 124.0, "aaa", "bbb");
459 lo_send(a, "/a/b/c/d", "sfsff", "one", 0.12345678f, "three",
460 -0.00000023001f, 1.0);
461 lo_send(a, "/a/b/c/d", "b", btest);
462
463 TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
464 "123", btest, midi_data, 0x0123456789abcdefULL, tt,
465 0.9999, "sym", 'X', 'Y', LO_ARGS_END) == 0);
466
467#ifdef __GNUC__
468 // Note: Lack of support for variable-argument macros in non-GCC compilers
469 // does not allow us to test for these conditions.
470
471 // too many args
472 TEST(test_varargs(a, "/lotsofformats", "f", 0.12345678f, 123,
473 "123", btest, midi_data, 0x0123456789abcdefULL, tt,
474 0.9999, "sym", 'X', 'Y', LO_ARGS_END) != 0);
475 // too many types
476 TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
477 "123", btest, midi_data, 0x0123456789abcdefULL, tt, 0.5,
478 LO_ARGS_END) != 0);
479#endif
480
481 // test lo_message_add
482 m1 = lo_message_new();
483 TEST(lo_message_add(m1, "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
484 btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
485 'X', 'Y') == 0);
486 lo_send_message(a, "/lotsofformats", m1);
487 lo_message_free(m1);
488
489 lo_blob_free(btest);
490
491 lo_send(a, "/pattern/*", "s", "a");
492 lo_send(a, "/pattern/ba[rz]", "s", "b");
493
494 server_url = lo_server_thread_get_url(st);
495 sprintf(cmd, "." PATHDELIM "subtest %s &", server_url);
496 if (system(cmd) != 0) {
497 fprintf(stderr, "Cannot execute subtest command\n");
498 exit(1);
499 }
500 system(cmd);
501 free(server_url);
502
503#ifdef WIN32
504 Sleep(2000);
505#else
506 sleep(2);
507#endif
508 TEST(reply_count == 3);
509 TEST(pattern_count == 5);
510 TEST(subtest_count == 2);
511 TEST(subtest_reply_count == 22);
512 printf("\n");
513
514 {
515 lo_timetag t = {10,0xFFFFFFFC};
516 b = lo_bundle_new(t);
517 }
518 m1 = lo_message_new();
519 lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
520 lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
521 lo_bundle_add_message(b, "/bundle", m1);
522 lo_send_bundle(a, b);
523
524 /* This should be safe for multiple copies of the same message. */
525 lo_bundle_free_messages(b);
526
527 {
528 lo_timetag t = {1,2};
529 b = lo_bundle_new(t);
530 }
531 m1 = lo_message_new();
532 lo_message_add_int32(m1, 23);
533 lo_message_add_string(m1, "23");
534 lo_bundle_add_message(b, "/bundle", m1);
535 m2 = lo_message_new();
536 lo_message_add_string(m2, "24");
537 lo_message_add_int32(m2, 24);
538 lo_bundle_add_message(b, "/bundle", m2);
539 lo_bundle_add_message(b, "/bundle", m1);
540
541/*
542 lo_send_bundle(a, b);
543 if (a->errnum) {
544 printf("error %d: %s\n", a->errnum, a->errstr);
545 exit(1);
546 }
547*/
548 TEST(lo_send_bundle(a, b) == 88);
549
550 /* Test freeing out-of-order copies of messages in a bundle. */
551 lo_bundle_free_messages(b);
552
553 {
554 lo_timetag t = {10,0xFFFFFFFE};
555 b = lo_bundle_new(t);
556 }
557 m1 = lo_message_new();
558 lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
559 lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
560 lo_bundle_add_message(b, "/bundle", m1);
561 lo_send_bundle(a, b);
562 lo_message_free(m1);
563 lo_bundle_free(b);
564
565 lo_timetag_now(&sched);
566
567 sched.sec += 5;
568 b = lo_bundle_new(sched);
569 m1 = lo_message_new();
570 lo_message_add_string(m1, "future");
571 lo_message_add_string(m1, "time");
572 lo_message_add_string(m1, "test");
573 lo_bundle_add_message(b, "/bundle", m1);
574
575 lo_send_bundle(a, b);
576 lo_message_free(m1);
577 lo_bundle_free(b);
578
579 lo_send_timestamped(a, sched, "/bundle", "s", "lo_send_timestamped() test");
580
581 /* test bundle timestamp ends up in message struct (and doesn't end up in
582 unbundled messages) */
583 lo_timetag_now(&sched);
584 lo_send_timestamped(a, sched, "/timestamp", "it", 1, sched);
585 lo_send(a, "/timestamp", "it", 0, sched);
586
587#define JITTER_ITS 25
588 /* jitter tests */
589 {
590 lo_timetag stamps[JITTER_ITS];
591 lo_timetag now;
592 int i;
593
594 for (i=0; i<JITTER_ITS; i++) {
595 lo_timetag_now(&now);
596 stamps[i] = now;
597 stamps[i].sec += 1;
598 stamps[i].frac = rand();
599 lo_send_timestamped(a, stamps[i], "/jitter", "ti", stamps[i], i);
600 }
601 }
602
603#ifdef WIN32
604 Sleep(2000);
605#else
606 sleep(2);
607#endif
608
609 lo_address_free(a);
610
611 TEST(lo_server_thread_events_pending(st));
612
613 while (lo_server_thread_events_pending(st)) {
614 printf("pending events, wait...\n");
615#ifdef WIN32
616 fflush(stdout);
617 Sleep(1000);
618#else
619 sleep(1);
620#endif
621 }
622
623 TEST(bundle_count == 7);
624 printf("\n");
625
626 printf("bundle timing jitter results:\n"
627 "max jitter = %fs\n"
628 "avg jitter = %fs\n"
629 "min jitter = %fs\n\n",
630 jitter_max, jitter_total/(float)jitter_count, jitter_min);
631
632 server_url = lo_server_get_url(s);
633
634 lo_server_add_method(s, NULL, NULL, generic_handler, NULL);
635 a = lo_address_new_from_url(server_url);
636 TEST(lo_server_recv_noblock(s, 0) == 0);
637 printf("Testing noblock API on %s\n", server_url);
638 lo_send(a, "/non-block-test", "f", 23.0);
639
640 count = 0;
641 while (!lo_server_recv_noblock(s, 10) && count++ < 1000) { }
642 if (count >= 1000) {
643 printf("lo_server_recv_noblock() test failed\n");
644
645 exit(1);
646 }
647
648 /* Delete methods */
649 lo_server_thread_del_method(st, "/coerce", "dfhiSs");
650 lo_server_del_method(s, NULL, NULL);
651
652 lo_address_free(a);
653 lo_server_free(s);
654 free(server_url);
655
656#ifndef WIN32
657 { /* UNIX domain tests */
658 lo_address ua;
659 lo_server us;
660 char *addr;
661
662 unlink("/tmp/testlo.osc");
663 us = lo_server_new_with_proto("/tmp/testlo.osc", LO_UNIX, error);
664 ua = lo_address_new_from_url("osc.unix:///tmp/testlo.osc");
665 TEST(lo_server_get_protocol(us) == LO_UNIX);
666 TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
667 TEST(lo_server_recv(us) == 16);
668 addr = lo_server_get_url(us);
669 TEST(!strcmp("osc.unix:////tmp/testlo.osc", addr));
670 free(addr);
671 lo_address_free(ua);
672 ua = lo_address_new_with_proto(LO_UNIX, NULL, "/tmp/testlo.osc");
673 TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
674 TEST(lo_server_recv(us) == 16);
675 lo_server_free(us);
676 lo_address_free(ua);
677 }
678#endif
679
680 { /* TCP tests */
681 lo_address ta;
682 lo_server ts;
683 char *addr;
684
685 ts = lo_server_new_with_proto(NULL, LO_TCP, error);
686 addr = lo_server_get_url(ts);
687 ta = lo_address_new_from_url(addr);
688 if (lo_address_errno(ta)) {
689 printf("err: %s\n", lo_address_errstr(ta));
690 exit(1);
691 }
692 TEST(lo_server_get_protocol(ts) == LO_TCP);
693 TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
694 TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
695 TEST(lo_server_recv(ts) == 16);
696 TEST(lo_server_recv(ts) == 16);
697 free(addr);
698 lo_server_free(ts);
699 lo_address_free(ta);
700 }
701
702 server_url = lo_server_thread_get_url(st);
703 a = lo_address_new_from_url(server_url);
704 /* exit */
705 lo_send(a, "/quit", NULL);
706 lo_address_free(a);
707
708 while (!done) {
709#ifdef WIN32
710 Sleep(1);
711#else
712 usleep(1000);
713#endif
714 }
715
716 lo_server_thread_free(st);
717 free(server_url);
718
719
720 return 0;
721}
722
723void exitcheck(void)
724{
725 if (!done) {
726 fprintf(stderr, "\ntest run not completed\n" PACKAGE_NAME
727 " test FAILED\n");
728 } else {
729 printf(PACKAGE_NAME " test PASSED\n");
730 }
731}
732
733void error(int num, const char *msg, const char *path)
734{
735 printf("liblo server error %d in %s: %s", num, path, msg);
736 if (!error_okay)
737 exit(1);
738 else
739 printf(" (expected)\n");
740}
741
742void rep_error(int num, const char *msg, const char *path)
743{
744 if (num != 9904) {
745 error(num, msg, path);
746 }
747}
748
749int generic_handler(const char *path, const char *types, lo_arg **argv,
750 int argc, lo_message data, void *user_data)
751{
752 int i;
753
754 printf("path: <%s>\n", path);
755 for (i=0; i<argc; i++) {
756 printf("arg %d '%c' ", i, types[i]);
757 lo_arg_pp(types[i], argv[i]);
758 printf("\n");
759 }
760 printf("\n");
761
762 return 1;
763}
764
765int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
766 lo_message data, void *user_data)
767{
768 lo_server serv = (lo_server)user_data;
769 lo_address src = lo_message_get_source(data);
770 char *url = lo_address_get_url(src);
771 char *server_url = lo_server_get_url(serv);
772 printf("Address of us: %s\n", server_url);
773 printf("%s <- f:%f, i:%d\n", path, argv[0]->f, argv[1]->i);
774 if (lo_send_from(src, serv, LO_TT_IMMEDIATE, "/reply", "s", "a reply") == -1) {
775 printf("OSC reply error %d: %s\nSending to %s\n", lo_address_errno(src), lo_address_errstr(src), url);
776 exit(1);
777 } else {
778 printf("Reply sent to %s\n\n", url);
779 }
780 free(server_url);
781 free(url);
782
783 return 0;
784}
785
786int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
787 lo_message data, void *user_data)
788{
789 lo_address src = lo_message_get_source(data);
790 char *url = lo_address_get_url(src);
791 printf("Reply received from %s\n", url);
792 free(url);
793 reply_count++;
794
795 return 0;
796}
797
798int lots_handler(const char *path, const char *types, lo_arg **argv, int argc,
799 lo_message data, void *user_data)
800{
801 lo_blob b;
802 unsigned char *d;
803
804 if (strcmp(path, "/lotsofformats")) {
805 fprintf(stderr, "path != /lotsofformats\n");
806 exit(1);
807 }
808 printf("path = %s\n", path);
809 TEST(types[0] == 'f' && argv[0]->f == 0.12345678f);
810 TEST(types[1] == 'i' && argv[1]->i == 123);
811 TEST(types[2] == 's' && !strcmp(&argv[2]->s, "123"));
812 b = (lo_blob)argv[3];
813 d = lo_blob_dataptr(b);
814 TEST(types[3] == 'b' && lo_blob_datasize(b) == 5);
815 TEST(d[0] == 'A' && d[1] == 'B' && d[2] == 'C' && d[3] == 'D' &&
816 d[4] == 'E');
817 d = argv[4]->m;
818 TEST(d[0] == 0xff && d[1] == 0xf7 && d[2] == 0xaa && d[3] == 0x00);
819 TEST(types[5] == 'h' && argv[5]->h == 0x0123456789ABCDEFULL);
820 TEST(types[6] == 't' && argv[6]->t.sec == 1 && \
821 argv[6]->t.frac == 0x80000000);
822 TEST(types[7] == 'd' && argv[7]->d == 0.9999);
823 TEST(types[8] == 'S' && !strcmp(&argv[8]->S, "sym"));
824printf("char: %d\n", argv[9]->c);
825 TEST(types[9] == 'c' && argv[9]->c == 'X');
826 TEST(types[10] == 'c' && argv[10]->c == 'Y');
827 TEST(types[11] == 'T');
828 TEST(types[12] == 'F');
829 TEST(types[13] == 'N');
830 TEST(types[14] == 'I');
831
832 printf("\n");
833
834 return 0;
835}
836
837int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc,
838 lo_message data, void *user_data)
839{
840 printf("path = %s\n", path);
841 TEST(types[0] == 'd' && fabs(argv[0]->d - 0.1) < FLT_EPSILON);
842 TEST(types[1] == 'f' && fabs(argv[1]->f - 0.2) < FLT_EPSILON);
843 TEST(types[2] == 'h' && argv[2]->h == 123);
844 TEST(types[3] == 'i' && argv[3]->i == 124);
845 TEST(types[4] == 'S' && !strcmp(&argv[4]->S, "aaa"));
846 TEST(types[5] == 's' && !strcmp(&argv[5]->s, "bbb"));
847 printf("\n");
848
849 return 0;
850}
851
852int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc,
853 lo_message data, void *user_data)
854{
855 bundle_count++;
856 printf("received bundle\n");
857
858 return 0;
859}
860
861int timestamp_handler(const char *path, const char *types, lo_arg **argv,
862 int argc, lo_message data, void *user_data)
863{
864 int bundled = argv[0]->i;
865
866 lo_timetag ts, arg_ts;
867 ts = lo_message_get_timestamp(data);
868 arg_ts = argv[1]->t;
869
870 if (bundled) {
871 TEST((ts.sec == arg_ts.sec) && (ts.frac == arg_ts.frac));
872 }
873 else {
874 TEST(ts.sec == LO_TT_IMMEDIATE.sec && ts.frac == LO_TT_IMMEDIATE.frac);
875 }
876 return 0;
877}
878
879int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc,
880 lo_message data, void *user_data)
881{
882 lo_timetag now;
883 float jitter;
884
885 lo_timetag_now(&now);
886 jitter = fabs(lo_timetag_diff(now, argv[0]->t));
887 jitter_count++;
888 //printf("jitter: %f\n", jitter);
889 printf("%d expected: %x:%x received %x:%x\n", argv[1]->i, argv[0]->t.sec,
890 argv[0]->t.frac, now.sec, now.frac);
891 jitter_total += jitter;
892 if (jitter > jitter_max) jitter_max = jitter;
893 if (jitter < jitter_min) jitter_min = jitter;
894
895 return 0;
896}
897
898int pattern_handler(const char *path, const char *types, lo_arg **argv,
899 int argc, lo_message data, void *user_data)
900{
901 pattern_count++;
902 printf("pattern matched %s\n", (char *)user_data);
903
904 return 0;
905}
906
907int subtest_handler(const char *path, const char *types, lo_arg **argv,
908 int argc, lo_message data, void *user_data)
909{
910 lo_address a = lo_message_get_source(data);
911
912 subtest_count++;
913 printf("got subtest message %d\n", subtest_count);
914 lo_send_from(a, lo_server_thread_get_server(user_data),
915 LO_TT_IMMEDIATE, "/subtest", "i", subtest_count);
916
917 return 0;
918}
919
920int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
921 int argc, lo_message data, void *user_data)
922{
923 subtest_reply_count++;
924 //printf("got subtest reply message %d\n", subtest_reply_count);
925
926 return 0;
927}
928
929int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
930 lo_message data, void *user_data)
931{
932 done = 1;
933
934 return 0;
935}
936
937int test_varargs(lo_address a, const char *path, const char *types, ...)
938{
939 va_list ap;
940 lo_message m = lo_message_new();
941 int error;
942 va_start(ap, types);
943 if ((error=lo_message_add_varargs(m, types, ap))==0)
944 lo_send_message(a, path, m);
945 else
946 printf("lo_message_add_varargs returned %d\n", error);
947 lo_message_free(m);
948 return error<0;
949}
950
951void replace_char(char *str, size_t size, const char find, const char replace)
952{
953 char *p = str;
954 while(size--)
955 {
956 if (find == *p) { *p = replace; }
957 ++p;
958 }
959}
960
961void test_deserialise()
962{
963 char *buf, *buf2, *tmp;
964 const char *types = NULL, *path;
965 lo_arg **argv = NULL;
966 size_t len, size;
967 char data[256];
968 int result = 0;
969
970 lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
971 uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
972 lo_timetag tt = {0x1, 0x80000000};
973 lo_blob b = NULL;
974
975 // build a message
976 lo_message msg = lo_message_new();
977 TEST(0 == lo_message_get_argc(msg));
978 lo_message_add_float(msg, 0.12345678f); // 0 f
979 lo_message_add_int32(msg, 123); // 1 i
980 lo_message_add_string(msg, "123"); // 2 s
981 lo_message_add_blob(msg, btest); // 3 b
982 lo_message_add_midi(msg, midi_data); // 4 m
983 lo_message_add_int64(msg, 0x0123456789abcdefULL); // 5 h
984 lo_message_add_timetag(msg, tt); // 6 t
985 lo_message_add_double(msg, 0.9999); // 7 d
986 lo_message_add_symbol(msg, "sym"); // 8 S
987 lo_message_add_char(msg, 'X'); // 9 c
988 lo_message_add_char(msg, 'Y'); // 10 c
989 lo_message_add_true(msg); // 11 T
990 lo_message_add_false(msg); // 12 F
991 lo_message_add_nil(msg); // 13 N
992 lo_message_add_infinitum(msg); // 14 I
993
994 // test types, args
995 TEST(15 == lo_message_get_argc(msg));
996 types = lo_message_get_types(msg);
997 TEST(NULL != types);
998 argv = lo_message_get_argv(msg);
999 TEST(NULL != argv);
1000 TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
1001 TEST('i' == types[1] && 123 == argv[1]->i);
1002 TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
1003 TEST('b' == types[3]);
1004 b = (lo_blob)argv[3];
1005 TEST(lo_blob_datasize(b) == sizeof(testdata));
1006 TEST(12 == lo_blobsize(b));
1007 TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
1008 TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4));
1009 TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h);
1010 TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
1011 TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
1012 TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym"));
1013 TEST('c' == types[9] && 'X' == argv[9]->c);
1014 TEST('c' == types[10] && 'Y' == argv[10]->c);
1015 TEST('T' == types[11] && NULL == argv[11]);
1016 TEST('F' == types[12] && NULL == argv[12]);
1017 TEST('N' == types[13] && NULL == argv[13]);
1018 TEST('I' == types[14] && NULL == argv[14]);
1019
1020 // serialise it
1021 len = lo_message_length(msg, "/foo");
1022 printf("serialise message_length=%d\n", (int)len);
1023 buf = calloc(len, sizeof(char));
1024 size = 0;
1025 tmp = lo_message_serialise(msg, "/foo", buf, &size);
1026 TEST(tmp == buf && size == len && 92 == len);
1027 lo_message_free(msg);
1028
1029 // deserialise it
1030 printf("deserialise\n");
1031 path = lo_get_path(buf, len);
1032 TEST(NULL != path && !strcmp(path, "/foo"));
1033 msg = lo_message_deserialise(buf, size, NULL);
1034 TEST(NULL != msg);
1035
1036 // repeat same test as above
1037 TEST(15 == lo_message_get_argc(msg));
1038 types = lo_message_get_types(msg);
1039 TEST(NULL != types);
1040 argv = lo_message_get_argv(msg);
1041 TEST(NULL != argv);
1042 TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
1043 TEST('i' == types[1] && 123 == argv[1]->i);
1044 TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
1045 TEST('b' == types[3]);
1046 b = (lo_blob)argv[3];
1047 TEST(lo_blob_datasize(b) == sizeof(testdata));
1048 TEST(12 == lo_blobsize(b));
1049 TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
1050 TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4));
1051 TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h);
1052 TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
1053 TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
1054 TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym"));
1055 TEST('c' == types[9] && 'X' == argv[9]->c);
1056 TEST('c' == types[10] && 'Y' == argv[10]->c);
1057 TEST('T' == types[11] && NULL == argv[11]);
1058 TEST('F' == types[12] && NULL == argv[12]);
1059 TEST('N' == types[13] && NULL == argv[13]);
1060 TEST('I' == types[14] && NULL == argv[14]);
1061
1062 // serialise it again, compare
1063 len = lo_message_length(msg, "/foo");
1064 printf("serialise message_length=%d\n", (int)len);
1065 buf2 = calloc(len, sizeof(char));
1066 size = 0;
1067 tmp = lo_message_serialise(msg, "/foo", buf2, &size);
1068 TEST(tmp == buf2 && size == len && 92 == len);
1069 TEST(!memcmp(buf, buf2, len));
1070 lo_message_free(msg);
1071
1072 lo_blob_free(btest);
1073 free(buf);
1074 free(buf2);
1075
1076 // deserialise failure tests with invalid message data
1077
1078 msg = lo_message_deserialise(data, 0, &result); // 0 size
1079 TEST(NULL == msg && LO_ESIZE == result);
1080
1081 snprintf(data, 256, "%s", "/foo"); // unterminated path string
1082 msg = lo_message_deserialise(data, 4, &result);
1083 TEST(NULL == msg && LO_EINVALIDPATH == result);
1084
1085 snprintf(data, 256, "%s", "/f_o"); // non-0 in pad area
1086 msg = lo_message_deserialise(data, 4, &result);
1087 TEST(NULL == msg && LO_EINVALIDPATH == result);
1088
1089 snprintf(data, 256, "%s", "/t__"); // types missing
1090 replace_char(data, 4, '_', '\0');
1091 msg = lo_message_deserialise(data, 4, &result);
1092 TEST(NULL == msg && LO_ENOTYPE == result);
1093
1094 snprintf(data, 256, "%s%s", "/t__", "____"); // types empty
1095 replace_char(data, 8, '_', '\0');
1096 msg = lo_message_deserialise(data, 8, &result);
1097 TEST(NULL == msg && LO_EBADTYPE == result);
1098
1099 snprintf(data, 256, "%s%s", "/t__", ",f_"); // short message
1100 replace_char(data, 7, '_', '\0');
1101 msg = lo_message_deserialise(data, 7, &result);
1102 TEST(NULL == msg && LO_EINVALIDTYPE == result);
1103
1104 snprintf(data, 256, "%s%s", "/t__", "ifi_"); // types missing comma
1105 replace_char(data, 8, '_', '\0');
1106 msg = lo_message_deserialise(data, 8, &result);
1107 TEST(NULL == msg && LO_EBADTYPE == result);
1108
1109 snprintf(data, 256, "%s%s", "/t__", ",ifi"); // types unterminated
1110 replace_char(data, 8, '_', '\0');
1111 msg = lo_message_deserialise(data, 8, &result);
1112 TEST(NULL == msg && LO_EINVALIDTYPE == result);
1113
1114 snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data
1115 replace_char(data, 8, '_', '\0');
1116 msg = lo_message_deserialise(data, 12, &result);
1117 TEST(NULL == msg && LO_EINVALIDARG == result);
1118
1119 snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data again
1120 replace_char(data, 8, '_', '\0');
1121 msg = lo_message_deserialise(data, 15, &result);
1122 TEST(NULL == msg && LO_EINVALIDARG == result);
1123
1124 snprintf(data, 256, "%s%s", "/t__", ",f__"); // too much arg data
1125 replace_char(data, 8, '_', '\0');
1126 msg = lo_message_deserialise(data, 16, &result);
1127 TEST(NULL == msg && LO_ESIZE == result);
1128
1129 snprintf(data, 256, "%s%s", "/t__", ",bs_"); // blob longer than msg length
1130 replace_char(data, 8, '_', '\0');
1131 *(uint32_t *)(data + 8) = lo_htoo32((uint32_t)99999);
1132 msg = lo_message_deserialise(data, 256, &result);
1133 TEST(NULL == msg && LO_EINVALIDARG == result);
1134}
1135
1136void test_validation(lo_address a)
1137{
1138 /* packet crafted to crash a lo_server when no input validation is performed */
1139 char mem[] = {"/\0\0\0,bs\0,\x00\x0F\x42\x3F"}; // OSC: "/" ",bs" 999999
1140 int eok = error_okay;
1141 int sock = a->socket;
1142
1143 /* This code won't work with MSVC because the lo_client_sockets data structure
1144 * is not explicitly made available to external programs. We could expose it
1145 * in debug mode, perhaps, but let's just skip this test for now. (Can be tested
1146 * on Windows using MingW.) */
1147#ifdef _MSC_VER
1148 return;
1149#else
1150
1151 printf("validation\n");
1152
1153 if (sock == -1)
1154 sock = lo_client_sockets.udp;
1155 if (sock == -1) {
1156 fprintf(stderr, "Couldn't get socket in test_validation(), %s:%d\n", __FILE__, __LINE__);
1157 exit(1);
1158 }
1159
1160 error_okay = 1;
1161 if (sendto(sock, &mem, sizeof(mem), MSG_NOSIGNAL,
1162 a->ai->ai_addr, a->ai->ai_addrlen)==-1) {
1163 fprintf(stderr, "Error sending packet in test_validation(), %s:%d\n", __FILE__, __LINE__);
1164 }
1165#ifndef WIN32
1166 usleep(10000);
1167#else
1168 Sleep(10);
1169#endif
1170 error_okay = eok;
1171#endif
1172}
1173
1174void test_multicast(lo_server_thread st)
1175{
1176 /* test multicast server and sender */
1177 /* message is sent from st otherwise reply doesn't work */
1178 lo_server ms = lo_server_new_multicast("224.0.1.1", "15432", error);
1179 lo_address ma = lo_address_new("224.0.1.1", "15432");
1180 lo_address_set_ttl(ma, 1);
1181 lo_server_add_method(ms, "/foo/bar", "fi", foo_handler, ms);
1182 lo_server_add_method(ms, "/reply", "s", reply_handler, NULL);
1183 if (lo_send_from(ma, lo_server_thread_get_server(st), LO_TT_IMMEDIATE,
1184 "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
1185 printf("multicast send error %d: %s\n", lo_address_errno(ma), lo_address_errstr(ma));
1186 exit(1);
1187 }
1188 TEST(lo_server_recv(ms)==24);
1189 lo_server_free(ms);
1190 lo_address_free(ma);
1191}
1192
1193/* vi:set ts=8 sts=4 sw=4: */