9 #include "error.h" |
9 #include "error.h" |
10 |
10 |
11 #include <stdlib.h> |
11 #include <stdlib.h> |
12 #include <string.h> |
12 #include <string.h> |
13 #include <assert.h> |
13 #include <assert.h> |
|
14 #include <ctype.h> |
|
15 |
|
16 #define DUMP_STR_BUF 1024 |
|
17 #define DUMP_STR_COUNT 8 |
|
18 #define DUMP_STR_TAIL 10 |
|
19 |
|
20 char *dump_str_append (char *buf, const char *str) |
|
21 { |
|
22 while (*str) |
|
23 *buf++ = *str++; |
|
24 |
|
25 return buf; |
|
26 } |
|
27 |
|
28 /** |
|
29 * This re-formats the given string to escape values, and returns a pointer to an internal static buffer. |
|
30 * |
|
31 * If len is given as >= 0, only the given number of chars will be dumped from str |
|
32 * |
|
33 * The buffer cycles a bit, so you pointers remain valid across DUMP_STR_COUNT calls. |
|
34 */ |
|
35 const char *dump_strn (const char *str, ssize_t len) |
|
36 { |
|
37 static char dump_buf[DUMP_STR_COUNT][DUMP_STR_BUF]; |
|
38 static size_t dump_idx = 0; |
|
39 |
|
40 // pick a buffer to use |
|
41 const char *str_ptr = str; |
|
42 char *buf_ptr = dump_buf[dump_idx++], *buf = buf_ptr; |
|
43 |
|
44 // cycle |
|
45 if (dump_idx >= DUMP_STR_COUNT) |
|
46 dump_idx = 0; |
|
47 |
|
48 // NULL? |
|
49 if (str == NULL) { |
|
50 buf = dump_str_append(buf, "NULL"); |
|
51 *buf = '\0'; |
|
52 |
|
53 return buf_ptr; |
|
54 } |
|
55 |
|
56 // quote |
|
57 *buf++ = '\''; |
|
58 |
|
59 // dump each char |
|
60 for (; *str && (size_t) (buf - buf_ptr) < DUMP_STR_BUF - DUMP_STR_TAIL && (len < 0 || (size_t) (str - str_ptr) < (size_t) len); str++) { |
|
61 if (*str == '\'') { |
|
62 buf = dump_str_append(buf, "\\'"); break; |
|
63 |
|
64 } else if (isprint(*str)) { |
|
65 *buf++ = *str; |
|
66 |
|
67 } else { |
|
68 switch (*str) { |
|
69 case '\r': |
|
70 buf = dump_str_append(buf, "\\r"); break; |
|
71 |
|
72 case '\n': |
|
73 buf = dump_str_append(buf, "\\n"); break; |
|
74 |
|
75 default: |
|
76 buf += snprintf(buf, (DUMP_STR_BUF - (buf - buf_ptr)), "\\x%02x", *str); |
|
77 break; |
|
78 } |
|
79 } |
|
80 } |
|
81 |
|
82 // quote |
|
83 *buf++ = '\''; |
|
84 |
|
85 // overflow? |
|
86 if ((size_t)(buf - buf_ptr) == DUMP_STR_BUF - DUMP_STR_TAIL) |
|
87 buf = dump_str_append(buf, "..."); |
|
88 |
|
89 // terminate |
|
90 *buf = '\0'; |
|
91 |
|
92 // ok |
|
93 return buf_ptr; |
|
94 } |
|
95 |
|
96 const char *dump_str (const char *str) |
|
97 { |
|
98 return dump_strn(str, -1); |
|
99 } |
14 |
100 |
15 void assert_strcmp (const char *is, const char *should_be) |
101 void assert_strcmp (const char *is, const char *should_be) |
16 { |
102 { |
17 if (strcmp(is, should_be)) |
103 if (strcmp(is, should_be)) |
18 FATAL("'%s' != '%s'", is, should_be); |
104 FATAL("%s != %s", dump_str(is), dump_str(should_be)); |
19 } |
105 } |
20 |
106 |
21 void assert_strncmp (const char *is, const char *should_be, size_t n) |
107 void assert_strncmp (const char *is, const char *should_be, size_t n) |
22 { |
108 { |
23 if (strncmp(is, should_be, n)) |
109 if (strncmp(is, should_be, n)) |
24 FATAL("'%s':%u != '%s'", is, (unsigned) n, should_be); |
110 FATAL("%s:%u != %s", dump_strn(is, n), (unsigned) n, dump_strn(should_be, n)); |
25 } |
111 } |
26 |
112 |
27 void assert_strlen (const char *str, size_t n) |
113 void assert_strlen (const char *str, size_t n) |
28 { |
114 { |
29 if (strlen(str) != n) |
115 if (strlen(str) != n) |
30 FATAL("strlen('%s') != %u", str, (unsigned) n); |
116 FATAL("strlen(%s) != %u", dump_str(str), (unsigned) n); |
31 } |
117 } |
32 |
118 |
33 void assert_strnull (const char *str) |
119 void assert_strnull (const char *str) |
34 { |
120 { |
35 if (str != NULL) |
121 if (str != NULL) |
36 FATAL("'%s' != NULL", str); |
122 FATAL("%s != NULL", dump_str(str)); |
37 } |
123 } |
38 |
124 |
39 void assert_success (err_t err) |
125 void assert_success (err_t err) |
40 { |
126 { |
41 if (err != SUCCESS) |
127 if (err != SUCCESS) |
57 |
143 |
58 void assert_sock_read (struct sock_stream *sock, const char *str) |
144 void assert_sock_read (struct sock_stream *sock, const char *str) |
59 { |
145 { |
60 char buf[strlen(str)]; |
146 char buf[strlen(str)]; |
61 |
147 |
62 log_debug("read: %p: '%s'", sock, str); |
148 log_debug("read: %p: %s", sock, dump_str(str)); |
63 |
149 |
64 // read it |
150 // read it |
65 assert(sock_stream_read(sock, buf, strlen(str)) == (int) strlen(str)); |
151 assert(sock_stream_read(sock, buf, strlen(str)) == (int) strlen(str)); |
66 |
152 |
67 // cmp |
153 // cmp |
68 assert_strncmp(buf, str, strlen(str)); |
154 assert_strncmp(buf, str, strlen(str)); |
69 } |
155 } |
70 |
156 |
71 void assert_sock_write (struct sock_stream *sock, const char *str) |
157 void assert_sock_write (struct sock_stream *sock, const char *str) |
72 { |
158 { |
73 log_debug("write: %p: '%s'", sock, str); |
159 log_debug("write: %p: %s", sock, dump_str(str)); |
74 |
160 |
75 // write it |
161 // write it |
76 assert(sock_stream_write(sock, str, strlen(str)) == (int) strlen(str)); |
162 assert(sock_stream_write(sock, str, strlen(str)) == (int) strlen(str)); |
77 } |
163 } |
78 |
164 |
91 char *buf; |
177 char *buf; |
92 size_t len; |
178 size_t len; |
93 |
179 |
94 sock_test_get_send_data(sock, &buf, &len); |
180 sock_test_get_send_data(sock, &buf, &len); |
95 |
181 |
96 log_debug("get_send_data: '%.*s'", (int) len, buf); |
182 log_debug("get_send_data: %s", dump_strn(buf, len)); |
97 |
183 |
98 // should be the same |
184 // should be the same |
99 assert_strncmp(buf, data, len); |
185 assert_strncmp(buf, data, len); |
100 assert_strlen(data, len); |
186 assert_strlen(data, len); |
101 |
187 |
102 // cleanup |
188 // cleanup |
103 free(buf); |
189 free(buf); |
|
190 } |
|
191 |
|
192 void test_dump_str (void) |
|
193 { |
|
194 log_info("dumping example strings on stdout:"); |
|
195 |
|
196 log_debug("normal: %s", dump_str("Hello World")); |
|
197 log_debug("escapes: %s", dump_str("foo\r\nbar\a\001")); |
|
198 log_debug("length: %s", dump_strn("<-->**", 4)); |
|
199 log_debug("overflow: %s", dump_str( "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); |
|
200 log_debug("null: %s", dump_str(NULL)); |
104 } |
201 } |
105 |
202 |
106 void test_sock_test (void) |
203 void test_sock_test (void) |
107 { |
204 { |
108 struct sock_test *sock = sock_test_create(); |
205 struct sock_test *sock = sock_test_create(); |
459 |
556 |
460 /** Test func */ |
557 /** Test func */ |
461 void (*func) (void); |
558 void (*func) (void); |
462 |
559 |
463 } _tests[] = { |
560 } _tests[] = { |
|
561 { "dump_str", &test_dump_str }, |
464 { "sock_test", &test_sock_test }, |
562 { "sock_test", &test_sock_test }, |
465 { "line_proto", &test_line_proto }, |
563 { "line_proto", &test_line_proto }, |
466 { "irc_conn", &test_irc_conn }, |
564 { "irc_conn", &test_irc_conn }, |
467 { "irc_net", &test_irc_net }, |
565 { "irc_net", &test_irc_net }, |
468 { NULL, NULL } |
566 { NULL, NULL } |