CSL  5.2
testlo.c
Go to the documentation of this file.
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 
54 union end_test32 {
55  uint32_t i;
56  char c[4];
57 };
58 
59 union end_test64 {
60  uint64_t i;
61  char c[8];
62 };
63 
64 static int done = 0;
65 static int bundle_count = 0;
66 static int pattern_count = 0;
67 static int reply_count = 0;
68 static int subtest_count = 0;
69 static int subtest_reply_count = 0;
70 static int error_okay = 0;
71 
72 char testdata[5] = "ABCDE";
73 
74 static int jitter_count = 0;
75 static float jitter_total = 0.0f;
76 static float jitter_max = 0.0f;
77 static float jitter_min = 1000.0f;
78 
79 void exitcheck(void);
80 void test_deserialise(void);
83 void error(int num, const char *m, const char *path);
84 void rep_error(int num, const char *m, const char *path);
85 
86 int generic_handler(const char *path, const char *types, lo_arg **argv,
87  int argc, lo_message data, void *user_data);
88 
89 int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
90  lo_message data, void *user_data);
91 
92 int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
93  lo_message data, void *user_data);
94 
95 int lots_handler(const char *path, const char *types, lo_arg **argv, int argc,
96  lo_message data, void *user_data);
97 
98 int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc,
99  lo_message data, void *user_data);
100 
101 int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc,
102  lo_message data, void *user_data);
103 
104 int timestamp_handler(const char *path, const char *types, lo_arg **argv,
105  int argc, lo_message data, void *user_data);
106 
107 int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc,
108  lo_message data, void *user_data);
109 
110 int pattern_handler(const char *path, const char *types, lo_arg **argv,
111  int argc, lo_message data, void *user_data);
112 
113 int subtest_handler(const char *path, const char *types, lo_arg **argv,
114  int argc, lo_message data, void *user_data);
115 
116 int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
117  int argc, lo_message data, void *user_data);
118 
119 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
120  lo_message data, void *user_data);
121 
122 int test_varargs(lo_address a, const char *path, const char *types, ...);
123 
124 int 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 
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  }
151 
152  /* leak check */
153  st = lo_server_thread_new(NULL, error);
155 #ifdef WIN32
156  Sleep(4);
157 #else
158  usleep(4000);
159 #endif
162  st = lo_server_thread_new(NULL, error);
166  st = lo_server_thread_new(NULL, error);
168  st = lo_server_thread_new(NULL, error);
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 
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 */
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. */
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. */
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 
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",
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");
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 
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  }
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 
717  free(server_url);
718 
719 
720  return 0;
721 }
722 
723 void 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 
733 void 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 
742 void rep_error(int num, const char *msg, const char *path)
743 {
744  if (num != 9904) {
745  error(num, msg, path);
746  }
747 }
748 
749 int 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 
765 int 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 
786 int 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 
798 int 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"));
824 printf("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 
837 int 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 
852 int 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 
861 int 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 
879 int 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 
898 int 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 
907 int subtest_handler(const char *path, const char *types, lo_arg **argv,
908  int argc, lo_message data, void *user_data)
909 {
911 
912  subtest_count++;
913  printf("got subtest message %d\n", subtest_count);
915  LO_TT_IMMEDIATE, "/subtest", "i", subtest_count);
916 
917  return 0;
918 }
919 
920 int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
921  int argc, lo_message data, void *user_data)
922 {
924  //printf("got subtest reply message %d\n", subtest_reply_count);
925 
926  return 0;
927 }
928 
929 int 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 
937 int test_varargs(lo_address a, const char *path, const char *types, ...)
938 {
939  va_list ap;
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 
951 void 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 
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 
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 
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);
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: */