1 #include <stdio.h>
2 #include <malloc.h>
3 #include <string.h>
4 #include <check.h>
5 #include "line.h"
6 #include "torture.h"
7 
8 static const char *malformed[] = {
9 	"PRIVMSG :foo :bar",
10 	":bar :bar PRIVMSG foo",
11 	"",
12 	": ",
13 	" ",
14 	NULL
15 };
16 
17 START_TEST(parser_empty)
18 	struct irc_line *l;
19 
20 	l = irc_parse_line("");
21 
22 	fail_unless(l->argc == 1);
23 
24 	l = irc_parse_line("\r\n");
25 
26 	fail_unless(l->argc == 1);
27 END_TEST
28 
29 START_TEST(parser_malformed)
30 	struct irc_line *l;
31 	char *raw;
32 	int j;
33 
34 	for (j = 0; malformed[j]; j++) {
35 		l = irc_parse_line(malformed[j]);
36 		if (!l) continue;
37 		raw = irc_line_string(l);
38 		free(raw);
39 		free_line(l);
40 	}
41 END_TEST
42 
43 #define NUM_RUNS 200
44 
45 START_TEST(parser_random)
46 	struct irc_line *l;
47 	char *raw;
48 	char buf[4096];
49 	FILE *f = fopen("/dev/urandom", "r");
50 	int j;
51 
52 	fail_if (!f, "Couldn't open /dev/urandom");
53 
54 	for (j = 0; j < 200; j++) {
55 		fail_if (!fgets(buf, sizeof(buf)-2, f), "error reading random data");
56 
57 		l = irc_parse_line(buf);
58 		if (!l) continue;
59 		raw = irc_line_string(l);
60 		free(raw);
61 		free_line(l);
62 	}
63 
64 	fclose(f);
65 END_TEST
66 
67 START_TEST(parser_vargs)
68 	struct irc_line *l = irc_parse_line_args( "FOO", "x", "y", NULL);
69 
70 	fail_if (!l);
71 	fail_if (strcmp(l->origin, "FOO") != 0);
72 	fail_if (l->argc != 2);
73 	fail_if (strcmp(l->args[0], "x") != 0);
74 	fail_if (strcmp(l->args[1], "y") != 0);
75 END_TEST
76 
77 START_TEST( parser_stringnl)
78 	struct irc_line l;
79 	char *ret;
80 	char *args[] = { "x", "y", "z", NULL };
81 	l.origin = "foobar";
82 	l.argc = 3;
83 	l.args = args;
84 	l.has_endcolon = WITHOUT_COLON;
85 
86 	ret = irc_line_string_nl(&l);
87 
88 	fail_if (strcmp(ret, ":foobar x y z\r\n") != 0);
89 END_TEST
90 
91 START_TEST(parser_get_nick)
92 	struct irc_line l;
93 	char *nick;
94 
95 	l.origin = "foobar";
96 	nick = line_get_nick(&l);
97 	fail_if (strcmp(nick, "foobar") != 0);
98 	l.origin = "foobar!~username@userhost";
99 	g_free(nick);
100 	nick = line_get_nick(&l);
101 	fail_if (strcmp(nick, "foobar") != 0);
102 	g_free(nick);
103 END_TEST
104 
105 START_TEST(parser_recv_line)
106 	GIOChannel *ch1, *ch2;
107 	struct irc_line *l;
108 	GIConv iconv;
109 
110 	g_io_channel_pair(&ch1, &ch2);
111 	g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL);
112 	g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL);
113 
114 	iconv = g_iconv_open("UTF-8", "UTF-8");
115 
116 	g_io_channel_write_chars(ch2, "PRIVMSG :bla\r\nFOO", -1, NULL, NULL);
117 	g_io_channel_flush(ch2, NULL);
118 
119 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_NORMAL);
120 	fail_unless(l->argc == 2);
121 	fail_unless(!strcmp(l->args[0], "PRIVMSG"));
122 	fail_unless(!strcmp(l->args[1], "bla"));
123 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_AGAIN);
124 
125 	g_iconv_close(iconv);
126 END_TEST
127 
128 START_TEST(parser_recv_line_invalid)
129 	GIOChannel *ch1, *ch2;
130 	struct irc_line *l;
131 	GIConv iconv;
132 
133 	g_io_channel_pair(&ch1, &ch2);
134 	g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL);
135 	g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL);
136 	g_io_channel_set_encoding(ch1, NULL, NULL);
137 	g_io_channel_set_encoding(ch2, NULL, NULL);
138 
139 	iconv = g_iconv_open("ISO8859-1", "UTF-8");
140 
141 	g_io_channel_write_chars(ch2, "PRIVMSG :bl\366a\r\n", -1, NULL, NULL);
142 	g_io_channel_flush(ch2, NULL);
143 
144 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_ERROR);
145 	fail_unless(!strcmp(l->args[1], "bl\366a"));
146 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_AGAIN);
147 
148 	g_iconv_close(iconv);
149 END_TEST
150 
151 
152 
153 START_TEST(parser_recv_line_iso8859)
154 	GIOChannel *ch1, *ch2;
155 	struct irc_line *l;
156 	GIConv iconv;
157 
158 	g_io_channel_pair(&ch1, &ch2);
159 	g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL);
160 	g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL);
161 	g_io_channel_set_encoding(ch1, NULL, NULL);
162 	g_io_channel_set_encoding(ch2, NULL, NULL);
163 
164 	iconv = g_iconv_open("UTF-8", "ISO8859-1");
165 
166 	fail_if(iconv == (GIConv)-1);
167 
168 	g_io_channel_write_chars(ch2, "PRIVMSG \366 p\r\n", -1, NULL, NULL);
169 	g_io_channel_flush(ch2, NULL);
170 
171 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_NORMAL);
172 	fail_unless(l->argc == 3);
173 	fail_unless(!strcmp(l->args[0], "PRIVMSG"));
174 	fail_unless(!strcmp(l->args[1], "ö"));
175 	fail_unless(irc_recv_line(ch1, iconv, NULL, &l) == G_IO_STATUS_AGAIN);
176 
177 	g_iconv_close(iconv);
178 END_TEST
179 
180 
181 
START_TEST(parser_dup)182 START_TEST(parser_dup)
183 	struct irc_line l, *m;
184 	char *args[] = { "x", "y", "z", NULL };
185 	l.origin = "bla";
186 	l.argc = 3;
187 	l.args = args;
188 	l.has_endcolon = 1;
189 
190 	m = linedup(&l);
191 
192 	fail_if (strcmp(l.origin, m->origin));
193 	fail_if (l.argc != m->argc);
194 	fail_if (strcmp(l.args[0], m->args[0]));
195 	fail_if (strcmp(l.args[1], m->args[1]));
196 	fail_if (strcmp(l.args[2], m->args[2]));
197 
198 	l.origin = NULL;
199 	m = linedup(&l);
200 	fail_if (m->origin);
201 END_TEST
202 
203 START_TEST(send_args)
204 	GIOChannel *ch1, *ch2;
205 	char *str;
206 
207 	g_io_channel_pair(&ch1, &ch2);
208 	g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL);
209 	g_io_channel_set_encoding(ch1, NULL, NULL);
210 	g_io_channel_set_encoding(ch2, NULL, NULL);
211 
212 	fail_unless(irc_send_args(ch1, (GIConv)-1, NULL, "PRIVMSG", "foo", NULL) == G_IO_STATUS_NORMAL);
213 
214 	g_io_channel_flush(ch1, NULL);
215 
216 	g_io_channel_read_line(ch2, &str, NULL, NULL, NULL);
217 
218 	fail_unless(!strcmp(str, "PRIVMSG :foo\r\n"));
219 END_TEST
220 
221 START_TEST(send_args_utf8)
222 	GIOChannel *ch1, *ch2;
223 	char *str;
224 	GIConv iconv;
225 
226 	iconv = g_iconv_open("ISO8859-1", "UTF-8");
227 
228 	g_io_channel_pair(&ch1, &ch2);
229 	g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL);
230 	g_io_channel_set_encoding(ch1, NULL, NULL);
231 	g_io_channel_set_encoding(ch2, NULL, NULL);
232 
233 	fail_unless(irc_send_args(ch1, iconv, NULL, "PRIVMSG", "fooö", NULL) == G_IO_STATUS_NORMAL);
234 
235 	g_iconv_close(iconv);
236 
237 	g_io_channel_flush(ch1, NULL);
238 
239 	g_io_channel_read_line(ch2, &str, NULL, NULL, NULL);
240 
241 	fail_unless(!strcmp(str, "PRIVMSG :foo\366\r\n"));
242 END_TEST
243 
parser_suite(void)244 Suite *parser_suite(void)
245 {
246 	Suite *s = suite_create("parser");
247 	TCase *tcase = tcase_create("core");
248 	suite_add_tcase(s, tcase);
249 	tcase_add_test(tcase, parser_vargs);
250 	tcase_add_test(tcase, parser_stringnl);
251 	tcase_add_test(tcase, parser_malformed);
252 	tcase_add_test(tcase, parser_random);
253 	tcase_add_test(tcase, parser_get_nick);
254 	tcase_add_test(tcase, parser_dup);
255 	tcase_add_test(tcase, parser_recv_line);
256 	tcase_add_test(tcase, parser_recv_line_iso8859);
257 	tcase_add_test(tcase, parser_recv_line_invalid);
258 	tcase_add_test(tcase, parser_empty);
259 	tcase_add_test(tcase, send_args);
260 	tcase_add_test(tcase, send_args_utf8);
261 	return s;
262 }
263