26 } |
26 } |
27 |
27 |
28 /** |
28 /** |
29 * This re-formats the given string to escape values, and returns a pointer to an internal static buffer. |
29 * This re-formats the given string to escape values, and returns a pointer to an internal static buffer. |
30 * |
30 * |
31 * If len is given as >= 0, only the given number of chars will be dumped from str |
31 * If len is given as >= 0, only the given number of chars will be dumped from str. |
32 * |
32 * |
33 * The buffer cycles a bit, so you pointers remain valid across DUMP_STR_COUNT calls. |
33 * The buffer cycles a bit, so the returned pointers remain valid across DUMP_STR_COUNT calls. |
34 * |
34 * |
35 * The resulting strings are truncated to (DUMP_STR_BUF - DUMP_STR_TAIL) bytes, not including the ending "...'\0" |
35 * The resulting string is truncated to (DUMP_STR_BUF - DUMP_STR_TAIL) bytes, not including the ending "...'\0". |
|
36 * |
|
37 * @param str the string to dump, should be NUL-terminated unless len is given |
|
38 * @param len if negative, ignored, otherwise, only this many bytes are dumped from str |
|
39 * @param return a pointer to a static buffer that remains valid across DUMP_STR_COUNT calls to this function |
36 */ |
40 */ |
37 const char *dump_strn (const char *str, ssize_t len) |
41 const char *dump_strn (const char *str, ssize_t len) |
38 { |
42 { |
39 static char dump_buf[DUMP_STR_COUNT][DUMP_STR_BUF]; |
43 static char dump_buf[DUMP_STR_COUNT][DUMP_STR_BUF]; |
40 static size_t dump_idx = 0; |
44 static size_t dump_idx = 0; |
79 buf = dump_str_append(buf, "\\\\"); |
83 buf = dump_str_append(buf, "\\\\"); |
80 |
84 |
81 } else if (isprint(*str)) { |
85 } else if (isprint(*str)) { |
82 // normal char |
86 // normal char |
83 *buf++ = *str; |
87 *buf++ = *str; |
84 |
88 |
85 } else { |
89 } else { |
86 // something more special |
90 // something more special |
87 switch (*str) { |
91 switch (*str) { |
88 case '\r': |
92 case '\r': |
89 buf = dump_str_append(buf, "\\r"); break; |
93 buf = dump_str_append(buf, "\\r"); break; |
118 return dump_strn(str, -1); |
122 return dump_strn(str, -1); |
119 } |
123 } |
120 |
124 |
121 void assert_strcmp (const char *is, const char *should_be) |
125 void assert_strcmp (const char *is, const char *should_be) |
122 { |
126 { |
123 if (strcmp(is, should_be)) |
127 if (!is || strcmp(is, should_be)) |
124 FATAL("%s != %s", dump_str(is), dump_str(should_be)); |
128 FATAL("%s != %s", dump_str(is), dump_str(should_be)); |
125 } |
129 } |
126 |
130 |
127 void assert_strncmp (const char *is, const char *should_be, size_t n) |
131 void assert_strncmp (const char *is, const char *should_be, size_t n) |
128 { |
132 { |
129 if (strncmp(is, should_be, n)) |
133 if (!is || strncmp(is, should_be, n)) |
130 FATAL("%s:%u != %s", dump_strn(is, n), (unsigned) n, dump_strn(should_be, n)); |
134 FATAL("%s:%u != %s", dump_strn(is, n), (unsigned) n, dump_strn(should_be, n)); |
131 } |
135 } |
132 |
136 |
133 void assert_strlen (const char *str, size_t n) |
137 void assert_strlen (const char *str, size_t n) |
134 { |
138 { |
135 if (strlen(str) != n) |
139 if (!str || strlen(str) != n) |
136 FATAL("strlen(%s) != %u", dump_str(str), (unsigned) n); |
140 FATAL("strlen(%s) != %u", dump_str(str), (unsigned) n); |
137 } |
141 } |
138 |
142 |
139 void assert_strnull (const char *str) |
143 void assert_strnull (const char *str) |
140 { |
144 { |
205 assert_strncmp(buf, data, len); |
208 assert_strncmp(buf, data, len); |
206 assert_strlen(data, len); |
209 assert_strlen(data, len); |
207 |
210 |
208 // cleanup |
211 // cleanup |
209 free(buf); |
212 free(buf); |
|
213 } |
|
214 |
|
215 /** |
|
216 * Nicer name for test_sock_add_recv_str |
|
217 */ |
|
218 void test_sock_push (struct sock_test *sock, const char *str) |
|
219 { |
|
220 return sock_test_add_recv_str(sock, str); |
210 } |
221 } |
211 |
222 |
212 void test_dump_str (void) |
223 void test_dump_str (void) |
213 { |
224 { |
214 log_info("dumping example strings on stdout:"); |
225 log_info("dumping example strings on stdout:"); |
265 log_debug("expect: %s", dump_str(line_str)); |
276 log_debug("expect: %s", dump_str(line_str)); |
266 |
277 |
267 assert_success(line_proto_recv(lp, &line_buf)); |
278 assert_success(line_proto_recv(lp, &line_buf)); |
268 |
279 |
269 if (line_str) { |
280 if (line_str) { |
270 assert(line_buf != NULL); |
|
271 assert_strcmp(line_buf, line_str); |
281 assert_strcmp(line_buf, line_str); |
272 |
282 |
273 } else { |
283 } else { |
274 assert_strnull(line_buf); |
284 assert_strnull(line_buf); |
275 |
285 |
437 assert_success(irc_conn_register(conn, ®ister_info)); |
447 assert_success(irc_conn_register(conn, ®ister_info)); |
438 assert_sock_data(sock, "NICK nick\r\nUSER user 0 * realname\r\n"); |
448 assert_sock_data(sock, "NICK nick\r\nUSER user 0 * realname\r\n"); |
439 |
449 |
440 // test on_register callback |
450 // test on_register callback |
441 if (noisy) log_info("test irc_conn_callbacks.on_register"); |
451 if (noisy) log_info("test irc_conn_callbacks.on_register"); |
442 sock_test_add_recv_str(sock, "001 mynick :Blaa blaa blaa\r\n"); |
452 test_sock_push(sock, "001 mynick :Blaa blaa blaa\r\n"); |
443 if (ctx) assert(ctx->on_registered); |
453 if (ctx) assert(ctx->on_registered); |
444 assert_strcmp(conn->nickname, "mynick"); |
454 assert_strcmp(conn->nickname, "mynick"); |
445 |
455 |
446 // ok |
456 // ok |
447 return conn; |
457 return conn; |
462 // add our test handlers |
472 // add our test handlers |
463 assert_success(irc_conn_add_cmd_handlers(conn, _conn_handlers, &ctx)); |
473 assert_success(irc_conn_add_cmd_handlers(conn, _conn_handlers, &ctx)); |
464 |
474 |
465 // test on_TEST handler |
475 // test on_TEST handler |
466 log_info("test irc_conn.handlers"); |
476 log_info("test irc_conn.handlers"); |
467 sock_test_add_recv_str(sock, ":foobar-prefix TEST arg0\r\n"); |
477 test_sock_push(sock, ":foobar-prefix TEST arg0\r\n"); |
468 assert(ctx.on_TEST); |
478 assert(ctx.on_TEST); |
469 |
479 |
470 // test PING/PONG |
480 // test PING/PONG |
471 log_info("test PING/PONG"); |
481 log_info("test PING/PONG"); |
472 sock_test_add_recv_str(sock, "PING foo\r\n"); |
482 test_sock_push(sock, "PING foo\r\n"); |
473 assert_sock_data(sock, "PONG foo\r\n"); |
483 assert_sock_data(sock, "PONG foo\r\n"); |
474 |
484 |
475 // quit nicely |
485 // quit nicely |
476 log_info("test QUIT"); |
486 log_info("test QUIT"); |
477 assert_success(irc_conn_QUIT(conn, "bye now")); |
487 assert_success(irc_conn_QUIT(conn, "bye now")); |
478 assert_sock_data(sock, "QUIT :bye now\r\n"); |
488 assert_sock_data(sock, "QUIT :bye now\r\n"); |
479 assert(conn->quitting); |
489 assert(conn->quitting); |
480 |
490 |
481 sock_test_add_recv_str(sock, "ERROR :Closing Link: Quit\r\n"); |
491 test_sock_push(sock, "ERROR :Closing Link: Quit\r\n"); |
482 sock_test_set_recv_eof(sock); |
492 sock_test_set_recv_eof(sock); |
483 assert(conn->quit && !conn->quitting && !conn->registered); |
493 assert(conn->quit && !conn->quitting && !conn->registered); |
484 assert(ctx.on_quit); |
494 assert(ctx.on_quit); |
485 assert(!ctx.on_error); |
495 assert(!ctx.on_error); |
486 |
496 |
542 // test register output |
552 // test register output |
543 assert_sock_data(sock, "NICK nick\r\nUSER user 0 * realname\r\n"); |
553 assert_sock_data(sock, "NICK nick\r\nUSER user 0 * realname\r\n"); |
544 |
554 |
545 // registration reply |
555 // registration reply |
546 log_info("test irc_conn_on_RPL_WELCOME"); |
556 log_info("test irc_conn_on_RPL_WELCOME"); |
547 sock_test_add_recv_str(sock, "001 mynick :Blaa blaa blaa\r\n"); |
557 test_sock_push(sock, "001 mynick :Blaa blaa blaa\r\n"); |
548 assert(net->conn->registered); |
558 assert(net->conn->registered); |
549 assert_strcmp(net->conn->nickname, "mynick"); |
559 assert_strcmp(net->conn->nickname, "mynick"); |
550 |
560 |
551 // JOIN request |
561 // JOIN request |
552 log_info("test irc_net_conn_registered -> irc_chan_join"); |
562 log_info("test irc_net_conn_registered -> irc_chan_join"); |
553 assert(chan->joining); |
563 assert(chan->joining); |
554 assert_sock_data(sock, "JOIN #test\r\n"); |
564 assert_sock_data(sock, "JOIN #test\r\n"); |
555 |
565 |
556 // JOIN reply |
566 // JOIN reply |
557 log_info("test irc_chan_on_JOIN"); |
567 log_info("test irc_chan_on_JOIN"); |
558 sock_test_add_recv_str(sock, ":mynick!user@host JOIN #test\r\n"); |
568 test_sock_push(sock, ":mynick!user@host JOIN #test\r\n"); |
559 assert(!chan->joining && chan->joined); |
569 assert(!chan->joining && chan->joined); |
560 assert(ctx.on_chan_self_join); |
570 assert(ctx.on_chan_self_join); |
561 |
571 |
562 // test errors by setting EOF |
572 // test errors by setting EOF |
563 log_info("test irc_net_error"); |
573 log_info("test irc_net_error"); |
587 { NULL, NULL } |
597 { NULL, NULL } |
588 }; |
598 }; |
589 |
599 |
590 int main (int argc, char **argv) |
600 int main (int argc, char **argv) |
591 { |
601 { |
|
602 const char *filter; |
592 struct test *test; |
603 struct test *test; |
593 |
604 |
594 (void) argv; |
605 if (argc == 1) { |
595 |
606 // no arguments |
596 // no arguments |
607 filter = NULL; |
597 assert(argc == 1); |
608 |
|
609 } else if (argc == 2) { |
|
610 // filter |
|
611 filter = argv[1]; |
|
612 |
|
613 log_info("only running tests: %s", filter); |
|
614 |
|
615 } else { |
|
616 FATAL("too many arguments"); |
|
617 } |
598 |
618 |
599 // run tests |
619 // run tests |
600 for (test = _tests; test->name; test++) { |
620 for (test = _tests; test->name; test++) { |
|
621 if (filter && strcmp(test->name, filter)) |
|
622 continue; |
|
623 |
601 log_info("Running test: %s", test->name); |
624 log_info("Running test: %s", test->name); |
602 |
625 |
603 test->func(); |
626 test->func(); |
604 } |
627 } |
605 |
628 |