| |
1 /* |
| |
2 * Purple - Internet Messaging Library |
| |
3 * Copyright (C) Pidgin Developers <devel@pidgin.im> |
| |
4 * |
| |
5 * This library is free software; you can redistribute it and/or |
| |
6 * modify it under the terms of the GNU Lesser General Public |
| |
7 * License as published by the Free Software Foundation; either |
| |
8 * version 2 of the License, or (at your option) any later version. |
| |
9 * |
| |
10 * This library is distributed in the hope that it will be useful, |
| |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| |
13 * Lesser General Public License for more details. |
| |
14 * |
| |
15 * You should have received a copy of the GNU Lesser General Public |
| |
16 * License along with this library; if not, see <https://www.gnu.org/licenses/>. |
| |
17 */ |
| |
18 |
| |
19 #include <glib.h> |
| |
20 |
| |
21 #include <purple.h> |
| |
22 |
| |
23 #include "../purpleircv3parser.h" |
| |
24 |
| |
25 typedef struct { |
| |
26 GHashTable *tags; |
| |
27 gchar *source; |
| |
28 gchar *command; |
| |
29 guint n_params; |
| |
30 const gchar * const params[16]; |
| |
31 } TestPurpleIRCv3ParserData; |
| |
32 |
| |
33 /****************************************************************************** |
| |
34 * Handlers |
| |
35 *****************************************************************************/ |
| |
36 static gboolean |
| |
37 test_purple_ircv3_test_handler(GHashTable *tags, const gchar *source, |
| |
38 const gchar *command, guint n_params, |
| |
39 GStrv params, GError **error, gpointer data) |
| |
40 { |
| |
41 TestPurpleIRCv3ParserData *d = data; |
| |
42 GHashTableIter iter; |
| |
43 |
| |
44 /* Make sure we have an expected tags hash table before checking them. */ |
| |
45 if(d->tags != NULL) { |
| |
46 gpointer expected_key; |
| |
47 gpointer expected_value; |
| |
48 guint actual_size; |
| |
49 guint expected_size; |
| |
50 |
| |
51 /* Make sure the tag hash tables have the same size. */ |
| |
52 expected_size = g_hash_table_size(d->tags); |
| |
53 actual_size = g_hash_table_size(tags); |
| |
54 g_assert_cmpuint(actual_size, ==, expected_size); |
| |
55 |
| |
56 /* Since the tables have the same size, we can walk through the expected |
| |
57 * table and use it to verify the actual table. |
| |
58 */ |
| |
59 g_hash_table_iter_init(&iter, d->tags); |
| |
60 while(g_hash_table_iter_next(&iter, &expected_key, &expected_value)) { |
| |
61 gpointer actual_value = NULL; |
| |
62 gboolean found = FALSE; |
| |
63 |
| |
64 found = g_hash_table_lookup_extended(tags, expected_key, NULL, |
| |
65 &actual_value); |
| |
66 g_assert_true(found); |
| |
67 g_assert_cmpstr(actual_value, ==, expected_value); |
| |
68 } |
| |
69 } |
| |
70 |
| |
71 /* If the expected strings values are NULL, set them to empty string as |
| |
72 * that's what g_match_info_get_named will return for them. |
| |
73 */ |
| |
74 if(d->source == NULL) { |
| |
75 d->source = ""; |
| |
76 } |
| |
77 |
| |
78 if(d->command == NULL) { |
| |
79 d->command = ""; |
| |
80 } |
| |
81 |
| |
82 /* Walk through the params checking against the expected values. */ |
| |
83 if(d->n_params > 0) { |
| |
84 g_assert_cmpuint(n_params, ==, d->n_params); |
| |
85 |
| |
86 for(guint i = 0; i < d->n_params; i++) { |
| |
87 g_assert_cmpstr(params[i], ==, d->params[i]); |
| |
88 } |
| |
89 } |
| |
90 |
| |
91 /* Validate all the string parameters. */ |
| |
92 g_assert_cmpstr(source, ==, d->source); |
| |
93 g_assert_cmpstr(command, ==, d->command); |
| |
94 |
| |
95 /* Cleanup everything the caller allocated. */ |
| |
96 g_clear_pointer(&d->tags, g_hash_table_destroy); |
| |
97 |
| |
98 /* Return the return value the caller asked for. */ |
| |
99 return TRUE; |
| |
100 } |
| |
101 |
| |
102 /****************************************************************************** |
| |
103 * Helpers |
| |
104 *****************************************************************************/ |
| |
105 static void |
| |
106 test_purple_ircv3_parser(const gchar *source, TestPurpleIRCv3ParserData *d) { |
| |
107 PurpleIRCv3Parser *parser = purple_ircv3_parser_new(); |
| |
108 GError *error = NULL; |
| |
109 gboolean result = FALSE; |
| |
110 |
| |
111 purple_ircv3_parser_set_fallback_handler(parser, |
| |
112 test_purple_ircv3_test_handler); |
| |
113 |
| |
114 result = purple_ircv3_parser_parse(parser, source, &error, d); |
| |
115 |
| |
116 g_assert_no_error(error); |
| |
117 g_assert_true(result); |
| |
118 |
| |
119 g_clear_object(&parser); |
| |
120 } |
| |
121 |
| |
122 /****************************************************************************** |
| |
123 * Tests |
| |
124 *****************************************************************************/ |
| |
125 static void |
| |
126 test_purple_ircv3_parser_simple(void) { |
| |
127 TestPurpleIRCv3ParserData data = { |
| |
128 .command = "foo", |
| |
129 .n_params = 3, |
| |
130 .params = {"bar", "baz", "asdf"}, |
| |
131 }; |
| |
132 |
| |
133 test_purple_ircv3_parser("foo bar baz asdf", &data); |
| |
134 } |
| |
135 |
| |
136 static void |
| |
137 test_purple_ircv3_parser_with_source(void) { |
| |
138 TestPurpleIRCv3ParserData data = { |
| |
139 .source = "coolguy", |
| |
140 .command = "foo", |
| |
141 .n_params = 3, |
| |
142 .params = {"bar", "baz", "asdf"}, |
| |
143 }; |
| |
144 |
| |
145 test_purple_ircv3_parser(":coolguy foo bar baz asdf", &data); |
| |
146 } |
| |
147 |
| |
148 static void |
| |
149 test_purple_ircv3_parser_with_trailing(void) { |
| |
150 TestPurpleIRCv3ParserData data = { |
| |
151 .command = "foo", |
| |
152 .n_params = 3, |
| |
153 .params = {"bar", "baz", "asdf quux"}, |
| |
154 }; |
| |
155 |
| |
156 test_purple_ircv3_parser("foo bar baz :asdf quux", &data); |
| |
157 } |
| |
158 |
| |
159 static void |
| |
160 test_purple_ircv3_parser_with_empty_trailing(void) { |
| |
161 TestPurpleIRCv3ParserData data = { |
| |
162 .command = "foo", |
| |
163 .n_params = 3, |
| |
164 .params = {"bar", "baz", ""}, |
| |
165 }; |
| |
166 |
| |
167 test_purple_ircv3_parser("foo bar baz :", &data); |
| |
168 } |
| |
169 |
| |
170 static void |
| |
171 test_purple_ircv3_parser_with_trailing_starting_colon(void) { |
| |
172 TestPurpleIRCv3ParserData data = { |
| |
173 .command = "foo", |
| |
174 .n_params = 3, |
| |
175 .params = {"bar", "baz", ":asdf"}, |
| |
176 }; |
| |
177 |
| |
178 test_purple_ircv3_parser("foo bar baz ::asdf", &data); |
| |
179 } |
| |
180 |
| |
181 static void |
| |
182 test_purple_ircv3_parser_with_source_and_trailing(void) { |
| |
183 TestPurpleIRCv3ParserData data = { |
| |
184 .source = "coolguy", |
| |
185 .command = "foo", |
| |
186 .n_params = 3, |
| |
187 .params = {"bar", "baz", "asdf quux"}, |
| |
188 }; |
| |
189 |
| |
190 test_purple_ircv3_parser(":coolguy foo bar baz :asdf quux", &data); |
| |
191 } |
| |
192 |
| |
193 static void |
| |
194 test_purple_ircv3_parser_with_source_and_trailing_whitespace(void) { |
| |
195 TestPurpleIRCv3ParserData data = { |
| |
196 .source = "coolguy", |
| |
197 .command = "foo", |
| |
198 .n_params = 3, |
| |
199 .params = {"bar", "baz", " asdf quux "}, |
| |
200 }; |
| |
201 |
| |
202 test_purple_ircv3_parser(":coolguy foo bar baz : asdf quux ", &data); |
| |
203 } |
| |
204 |
| |
205 static void |
| |
206 test_purple_ircv3_parser_with_source_and_trailing_colon(void) { |
| |
207 TestPurpleIRCv3ParserData data = { |
| |
208 .source = "coolguy", |
| |
209 .command = "PRIVMSG", |
| |
210 .n_params = 2, |
| |
211 .params = {"bar", "lol :) "}, |
| |
212 }; |
| |
213 |
| |
214 test_purple_ircv3_parser(":coolguy PRIVMSG bar :lol :) ", &data); |
| |
215 } |
| |
216 |
| |
217 static void |
| |
218 test_purple_ircv3_parser_with_source_and_empty_trailing(void) { |
| |
219 TestPurpleIRCv3ParserData data = { |
| |
220 .source = "coolguy", |
| |
221 .command = "foo", |
| |
222 .n_params = 3, |
| |
223 .params = {"bar", "baz", ""}, |
| |
224 }; |
| |
225 |
| |
226 test_purple_ircv3_parser(":coolguy foo bar baz :", &data); |
| |
227 } |
| |
228 |
| |
229 static void |
| |
230 test_purple_ircv3_parser_with_source_and_trailing_only_whitespace(void) { |
| |
231 TestPurpleIRCv3ParserData data = { |
| |
232 .source = "coolguy", |
| |
233 .command = "foo", |
| |
234 .n_params = 3, |
| |
235 .params = {"bar", "baz", " "}, |
| |
236 }; |
| |
237 |
| |
238 test_purple_ircv3_parser(":coolguy foo bar baz : ", &data); |
| |
239 } |
| |
240 |
| |
241 static void |
| |
242 test_purple_ircv3_parser_with_tags(void) { |
| |
243 TestPurpleIRCv3ParserData data = { |
| |
244 .command = "foo", |
| |
245 }; |
| |
246 |
| |
247 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
248 g_hash_table_insert(data.tags, "a", "b"); |
| |
249 g_hash_table_insert(data.tags, "c", "32"); |
| |
250 g_hash_table_insert(data.tags, "k", ""); |
| |
251 g_hash_table_insert(data.tags, "rt", "ql7"); |
| |
252 |
| |
253 test_purple_ircv3_parser("@a=b;c=32;k;rt=ql7 foo", &data); |
| |
254 } |
| |
255 |
| |
256 static void |
| |
257 test_purple_ircv3_parser_with_escaped_tags(void) { |
| |
258 #if 0 |
| |
259 /* Escaped tags aren't implemented yet. */ |
| |
260 TestPurpleIRCv3ParserData data = { |
| |
261 .command = "foo", |
| |
262 }; |
| |
263 |
| |
264 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
265 g_hash_table_insert(data.tags, "a", "b\\and\nk"); |
| |
266 g_hash_table_insert(data.tags, "c", "72 45"); |
| |
267 g_hash_table_insert(data.tags, "d", "gh;764"); |
| |
268 |
| |
269 test_purple_ircv3_parser("@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo", |
| |
270 &data); |
| |
271 #endif |
| |
272 } |
| |
273 |
| |
274 static void |
| |
275 test_purple_ircv3_with_tags_and_source(void) { |
| |
276 TestPurpleIRCv3ParserData data = { |
| |
277 .source = "quux", |
| |
278 .command = "ab", |
| |
279 .n_params = 1, |
| |
280 .params = {"cd"}, |
| |
281 }; |
| |
282 |
| |
283 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
284 g_hash_table_insert(data.tags, "c", ""); |
| |
285 g_hash_table_insert(data.tags, "h", ""); |
| |
286 g_hash_table_insert(data.tags, "a", "b"); |
| |
287 |
| |
288 test_purple_ircv3_parser("@c;h=;a=b :quux ab cd", &data); |
| |
289 } |
| |
290 |
| |
291 static void |
| |
292 test_purple_ircv3_last_param_no_colon(void) { |
| |
293 TestPurpleIRCv3ParserData data = { |
| |
294 .source = "src", |
| |
295 .command = "JOIN", |
| |
296 .n_params = 1, |
| |
297 .params = {"#chan"}, |
| |
298 }; |
| |
299 |
| |
300 test_purple_ircv3_parser(":src JOIN #chan", &data); |
| |
301 } |
| |
302 |
| |
303 static void |
| |
304 test_purple_ircv3_last_param_with_colon(void) { |
| |
305 TestPurpleIRCv3ParserData data = { |
| |
306 .source = "src", |
| |
307 .command = "JOIN", |
| |
308 .n_params = 1, |
| |
309 .params = {"#chan"}, |
| |
310 }; |
| |
311 |
| |
312 test_purple_ircv3_parser(":src JOIN :#chan", &data); |
| |
313 } |
| |
314 |
| |
315 static void |
| |
316 test_purple_ircv3_without_last_param(void) { |
| |
317 TestPurpleIRCv3ParserData data = { |
| |
318 .source = "src", |
| |
319 .command = "AWAY", |
| |
320 }; |
| |
321 |
| |
322 test_purple_ircv3_parser(":src AWAY", &data); |
| |
323 } |
| |
324 |
| |
325 static void |
| |
326 test_purple_ircv3_with_last_param(void) { |
| |
327 TestPurpleIRCv3ParserData data = { |
| |
328 .source = "src", |
| |
329 .command = "AWAY", |
| |
330 }; |
| |
331 |
| |
332 test_purple_ircv3_parser(":src AWAY ", &data); |
| |
333 } |
| |
334 |
| |
335 static void |
| |
336 test_purple_ircv3_tab_is_not_space(void) { |
| |
337 TestPurpleIRCv3ParserData data = { |
| |
338 .source = "cool\tguy", |
| |
339 .command = "foo", |
| |
340 .n_params = 2, |
| |
341 .params = {"bar", "baz"}, |
| |
342 }; |
| |
343 |
| |
344 test_purple_ircv3_parser(":cool\tguy foo bar baz", &data); |
| |
345 } |
| |
346 |
| |
347 static void |
| |
348 test_purple_ircv3_source_control_characters_1(void) { |
| |
349 /* Break each string after the hex escape as they are supposed to only be |
| |
350 * a single byte, but the c compiler will keep unescaping unless we break |
| |
351 * the string. |
| |
352 */ |
| |
353 TestPurpleIRCv3ParserData data = { |
| |
354 .source = "coolguy!ag@net\x03" "5w\x03" "ork.admin", |
| |
355 .command = "PRIVMSG", |
| |
356 .n_params = 2, |
| |
357 .params = {"foo", "bar baz"}, |
| |
358 }; |
| |
359 const gchar *msg = NULL; |
| |
360 |
| |
361 msg = ":coolguy!ag@net\x03" "5w\x03" "ork.admin PRIVMSG foo :bar baz"; |
| |
362 |
| |
363 test_purple_ircv3_parser(msg, &data); |
| |
364 } |
| |
365 |
| |
366 static void |
| |
367 test_purple_ircv3_source_control_characters_2(void) { |
| |
368 /* Break each string after the hex escape as they are supposed to only be |
| |
369 * a single byte, but the c compiler will keep unescaping unless we break |
| |
370 * the string. |
| |
371 */ |
| |
372 TestPurpleIRCv3ParserData data = { |
| |
373 .source = "coolguy!~ag@n\x02" "et\x03" "05w\x0f" "ork.admin", |
| |
374 .command = "PRIVMSG", |
| |
375 .n_params = 2, |
| |
376 .params = {"foo", "bar baz"}, |
| |
377 }; |
| |
378 const gchar *msg = NULL; |
| |
379 |
| |
380 msg = ":coolguy!~ag@n\x02" "et\x03" "05w\x0f" "ork.admin PRIVMSG foo :bar " |
| |
381 "baz"; |
| |
382 |
| |
383 test_purple_ircv3_parser(msg, &data); |
| |
384 } |
| |
385 |
| |
386 static void |
| |
387 test_purple_ircv3_everything(void) { |
| |
388 TestPurpleIRCv3ParserData data = { |
| |
389 .source = "irc.example.com", |
| |
390 .command = "COMMAND", |
| |
391 .n_params = 3, |
| |
392 .params = {"param1", "param2", "param3 param3"}, |
| |
393 }; |
| |
394 const gchar *msg = NULL; |
| |
395 |
| |
396 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
397 g_hash_table_insert(data.tags, "tag1", "value1"); |
| |
398 g_hash_table_insert(data.tags, "tag2", ""); |
| |
399 g_hash_table_insert(data.tags, "vendor1/tag3", "value2"); |
| |
400 g_hash_table_insert(data.tags, "vendor2/tag4", ""); |
| |
401 |
| |
402 msg = "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= " |
| |
403 ":irc.example.com COMMAND param1 param2 :param3 param3"; |
| |
404 |
| |
405 test_purple_ircv3_parser(msg, &data); |
| |
406 } |
| |
407 |
| |
408 static void |
| |
409 test_purple_ircv3_everything_but_tags(void) { |
| |
410 TestPurpleIRCv3ParserData data = { |
| |
411 .source = "irc.example.com", |
| |
412 .command = "COMMAND", |
| |
413 .n_params = 3, |
| |
414 .params = {"param1", "param2", "param3 param3"}, |
| |
415 }; |
| |
416 const gchar *msg = NULL; |
| |
417 |
| |
418 msg = ":irc.example.com COMMAND param1 param2 :param3 param3"; |
| |
419 |
| |
420 test_purple_ircv3_parser(msg, &data); |
| |
421 } |
| |
422 |
| |
423 static void |
| |
424 test_purple_ircv3_everything_but_source(void) { |
| |
425 TestPurpleIRCv3ParserData data = { |
| |
426 .command = "COMMAND", |
| |
427 .n_params = 3, |
| |
428 .params = {"param1", "param2", "param3 param3"}, |
| |
429 }; |
| |
430 const gchar *msg = NULL; |
| |
431 |
| |
432 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
433 g_hash_table_insert(data.tags, "tag1", "value1"); |
| |
434 g_hash_table_insert(data.tags, "tag2", ""); |
| |
435 g_hash_table_insert(data.tags, "vendor1/tag3", "value2"); |
| |
436 g_hash_table_insert(data.tags, "vendor2/tag4", ""); |
| |
437 |
| |
438 msg = "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4 " |
| |
439 "COMMAND param1 param2 :param3 param3"; |
| |
440 |
| |
441 test_purple_ircv3_parser(msg, &data); |
| |
442 } |
| |
443 |
| |
444 static void |
| |
445 test_purple_ircv3_command_only(void) { |
| |
446 TestPurpleIRCv3ParserData data = { |
| |
447 .command = "COMMAND", |
| |
448 }; |
| |
449 |
| |
450 test_purple_ircv3_parser("COMMAND", &data); |
| |
451 } |
| |
452 |
| |
453 static void |
| |
454 test_purple_ircv3_slashes_are_fun(void) { |
| |
455 #if 0 |
| |
456 /* Escaped tags aren't implemented yet. */ |
| |
457 TestPurpleIRCv3ParserData data = { |
| |
458 .command = "COMMAND", |
| |
459 }; |
| |
460 |
| |
461 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
462 g_hash_table_insert(data.tags, "foo", "\\\\;\\s \r\n"); |
| |
463 |
| |
464 test_purple_ircv3_parser("@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND", &data); |
| |
465 #endif |
| |
466 } |
| |
467 |
| |
468 static void |
| |
469 test_purple_ircv3_unreal_broken_1(void) { |
| |
470 TestPurpleIRCv3ParserData data = { |
| |
471 .source = "gravel.mozilla.org", |
| |
472 .command = "432", |
| |
473 .n_params = 2, |
| |
474 .params = {"#momo", "Erroneous Nickname: Illegal characters"}, |
| |
475 }; |
| |
476 const gchar *msg = NULL; |
| |
477 |
| |
478 msg = ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal " |
| |
479 "characters"; |
| |
480 |
| |
481 test_purple_ircv3_parser(msg, &data); |
| |
482 } |
| |
483 |
| |
484 static void |
| |
485 test_purple_ircv3_unreal_broken_2(void) { |
| |
486 TestPurpleIRCv3ParserData data = { |
| |
487 .source = "gravel.mozilla.org", |
| |
488 .command = "MODE", |
| |
489 .n_params = 2, |
| |
490 .params = {"#tckk", "+n"}, |
| |
491 }; |
| |
492 |
| |
493 test_purple_ircv3_parser(":gravel.mozilla.org MODE #tckk +n ", &data); |
| |
494 } |
| |
495 |
| |
496 static void |
| |
497 test_purple_ircv3_unreal_broken_3(void) { |
| |
498 TestPurpleIRCv3ParserData data = { |
| |
499 .source = "services.esper.net", |
| |
500 .command = "MODE", |
| |
501 .n_params = 3, |
| |
502 .params = {"#foo-bar", "+o", "foobar"}, |
| |
503 }; |
| |
504 |
| |
505 test_purple_ircv3_parser(":services.esper.net MODE #foo-bar +o foobar ", |
| |
506 &data); |
| |
507 } |
| |
508 |
| |
509 static void |
| |
510 test_purple_ircv3_tag_escape_char_at_a_time(void) { |
| |
511 #if 0 |
| |
512 /* Escaped tags aren't implemented yet. */ |
| |
513 TestPurpleIRCv3ParserData data = { |
| |
514 .command = "COMMAND", |
| |
515 }; |
| |
516 |
| |
517 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
518 g_hash_table_insert(data.tags, "tag1", "value\\ntest"); |
| |
519 |
| |
520 test_purple_ircv3_parser("@tag1=value\\\\ntest COMMAND", &data); |
| |
521 #endif |
| |
522 } |
| |
523 |
| |
524 static void |
| |
525 test_purple_ircv3_tag_drop_unnecessary_escapes(void) { |
| |
526 #if 0 |
| |
527 TestPurpleIRCv3ParserData data = { |
| |
528 .command = "COMMAND", |
| |
529 }; |
| |
530 |
| |
531 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
532 g_hash_table_insert(data.tags, "tag1", "value1"); |
| |
533 |
| |
534 test_purple_ircv3_parser("@tag1=value\\1 COMMAND", &data); |
| |
535 #endif |
| |
536 } |
| |
537 |
| |
538 static void |
| |
539 test_purple_ircv3_tag_drop_trailing_slash(void) { |
| |
540 #if 0 |
| |
541 /* Escaped tags aren't implemented yet. */ |
| |
542 TestPurpleIRCv3ParserData data = { |
| |
543 .command = "COMMAND", |
| |
544 }; |
| |
545 |
| |
546 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
547 g_hash_table_insert(data.tags, "tag1", "value1"); |
| |
548 |
| |
549 test_purple_ircv3_parser("@tag1=value1\\ COMMAND", &data); |
| |
550 #endif |
| |
551 } |
| |
552 |
| |
553 static void |
| |
554 test_purple_ircv3_duplicate_tags(void) { |
| |
555 TestPurpleIRCv3ParserData data = { |
| |
556 .command = "COMMAND", |
| |
557 }; |
| |
558 |
| |
559 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
560 g_hash_table_insert(data.tags, "tag1", "5"); |
| |
561 g_hash_table_insert(data.tags, "tag2", "3"); |
| |
562 g_hash_table_insert(data.tags, "tag3", "4"); |
| |
563 |
| |
564 test_purple_ircv3_parser("@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND", &data); |
| |
565 } |
| |
566 |
| |
567 static void |
| |
568 test_purple_ircv3_vendor_tags_are_namespaced(void) { |
| |
569 TestPurpleIRCv3ParserData data = { |
| |
570 .command = "COMMAND", |
| |
571 }; |
| |
572 const gchar *msg = NULL; |
| |
573 |
| |
574 data.tags = g_hash_table_new(g_str_hash, g_str_equal); |
| |
575 g_hash_table_insert(data.tags, "tag1", "5"); |
| |
576 g_hash_table_insert(data.tags, "tag2", "3"); |
| |
577 g_hash_table_insert(data.tags, "tag3", "4"); |
| |
578 g_hash_table_insert(data.tags, "vendor/tag2", "8"); |
| |
579 |
| |
580 msg = "@tag1=1;tag2=3;tag3=4;tag1=5;vendor/tag2=8 COMMAND"; |
| |
581 |
| |
582 test_purple_ircv3_parser(msg, &data); |
| |
583 } |
| |
584 |
| |
585 static void |
| |
586 test_purple_ircv3_special_mode_1(void) { |
| |
587 TestPurpleIRCv3ParserData data = { |
| |
588 .source = "SomeOp", |
| |
589 .command = "MODE", |
| |
590 .n_params = 2, |
| |
591 .params = {"#channel", "+i"}, |
| |
592 }; |
| |
593 |
| |
594 test_purple_ircv3_parser(":SomeOp MODE #channel :+i", &data); |
| |
595 } |
| |
596 |
| |
597 static void |
| |
598 test_purple_ircv3_special_mode_2(void) { |
| |
599 TestPurpleIRCv3ParserData data = { |
| |
600 .source = "SomeOp", |
| |
601 .command = "MODE", |
| |
602 .n_params = 4, |
| |
603 .params = {"#channel", "+oo", "SomeUser", "AnotherUser"}, |
| |
604 }; |
| |
605 |
| |
606 test_purple_ircv3_parser(":SomeOp MODE #channel +oo SomeUser :AnotherUser", |
| |
607 &data); |
| |
608 } |
| |
609 |
| |
610 /****************************************************************************** |
| |
611 * Main |
| |
612 *****************************************************************************/ |
| |
613 gint |
| |
614 main(gint argc, gchar *argv[]) { |
| |
615 g_test_init(&argc, &argv, NULL); |
| |
616 |
| |
617 /* These tests are based on the msg-split tests from |
| |
618 * https://github.com/ircdocs/parser-tests/blob/master/tests/msg-split.yaml |
| |
619 */ |
| |
620 g_test_add_func("/ircv3/parser/simple", |
| |
621 test_purple_ircv3_parser_simple); |
| |
622 g_test_add_func("/ircv3/parser/with-source", |
| |
623 test_purple_ircv3_parser_with_source); |
| |
624 g_test_add_func("/ircv3/parser/with-trailing", |
| |
625 test_purple_ircv3_parser_with_trailing); |
| |
626 g_test_add_func("/ircv3/parser/with-empty-trailing", |
| |
627 test_purple_ircv3_parser_with_empty_trailing); |
| |
628 g_test_add_func("/ircv3/parser/with-trailing-starting-colon", |
| |
629 test_purple_ircv3_parser_with_trailing_starting_colon); |
| |
630 g_test_add_func("/ircv3/parser/with-source-and-trailing", |
| |
631 test_purple_ircv3_parser_with_source_and_trailing); |
| |
632 g_test_add_func("/ircv3/parser/with-source-and-trailing-whitespace", |
| |
633 test_purple_ircv3_parser_with_source_and_trailing_whitespace); |
| |
634 g_test_add_func("/ircv3/parser/with-source-and-trailing-colon", |
| |
635 test_purple_ircv3_parser_with_source_and_trailing_colon); |
| |
636 g_test_add_func("/ircv3/parser/with-source-and-empty-trailing", |
| |
637 test_purple_ircv3_parser_with_source_and_empty_trailing); |
| |
638 g_test_add_func("/ircv3/parser/with-source-and-trailing-only-whitespace", |
| |
639 test_purple_ircv3_parser_with_source_and_trailing_only_whitespace); |
| |
640 |
| |
641 g_test_add_func("/ircv3/parser/with-tags", |
| |
642 test_purple_ircv3_parser_with_tags); |
| |
643 g_test_add_func("/ircv3/parser/with-escaped-tags", |
| |
644 test_purple_ircv3_parser_with_escaped_tags); |
| |
645 g_test_add_func("/ircv3/parser/with-tags-and-source", |
| |
646 test_purple_ircv3_with_tags_and_source); |
| |
647 |
| |
648 g_test_add_func("/ircv3/parser/last-param-no-colon", |
| |
649 test_purple_ircv3_last_param_no_colon); |
| |
650 g_test_add_func("/ircv3/parser/last-param-with-colon", |
| |
651 test_purple_ircv3_last_param_with_colon); |
| |
652 |
| |
653 g_test_add_func("/ircv3/parser/without-last-param", |
| |
654 test_purple_ircv3_without_last_param); |
| |
655 g_test_add_func("/ircv3/parser/with-last-parsm", |
| |
656 test_purple_ircv3_with_last_param); |
| |
657 |
| |
658 g_test_add_func("/ircv3/parser/tab-is-not-space", |
| |
659 test_purple_ircv3_tab_is_not_space); |
| |
660 |
| |
661 g_test_add_func("/ircv3/parser/source_control_characters_1", |
| |
662 test_purple_ircv3_source_control_characters_1); |
| |
663 g_test_add_func("/ircv3/parser/source_control_characters_2", |
| |
664 test_purple_ircv3_source_control_characters_2); |
| |
665 |
| |
666 g_test_add_func("/ircv3/parser/everything", |
| |
667 test_purple_ircv3_everything); |
| |
668 g_test_add_func("/ircv3/parser/everything-but-tags", |
| |
669 test_purple_ircv3_everything_but_tags); |
| |
670 g_test_add_func("/ircv3/parser/everything-but-source", |
| |
671 test_purple_ircv3_everything_but_source); |
| |
672 |
| |
673 g_test_add_func("/ircv3/parser/command-only", |
| |
674 test_purple_ircv3_command_only); |
| |
675 |
| |
676 g_test_add_func("/ircv3/parser/slashes-are-fun", |
| |
677 test_purple_ircv3_slashes_are_fun); |
| |
678 |
| |
679 g_test_add_func("/ircv3/parser/unreal-broken-1", |
| |
680 test_purple_ircv3_unreal_broken_1); |
| |
681 g_test_add_func("/ircv3/parser/unreal-broken-2", |
| |
682 test_purple_ircv3_unreal_broken_2); |
| |
683 g_test_add_func("/ircv3/parser/unreal-broken-3", |
| |
684 test_purple_ircv3_unreal_broken_3); |
| |
685 |
| |
686 g_test_add_func("/ircv3/parser/tag-escape-char-at-a-time", |
| |
687 test_purple_ircv3_tag_escape_char_at_a_time); |
| |
688 g_test_add_func("/ircv3/parser/tag-drop-unnecessary-escapes", |
| |
689 test_purple_ircv3_tag_drop_unnecessary_escapes); |
| |
690 g_test_add_func("/ircv3/parser/tag-drop-trailing-slash", |
| |
691 test_purple_ircv3_tag_drop_trailing_slash); |
| |
692 |
| |
693 g_test_add_func("/ircv3/parser/duplicate-tags", |
| |
694 test_purple_ircv3_duplicate_tags); |
| |
695 g_test_add_func("/ircv3/parser/vendor-tags-are-namespaced", |
| |
696 test_purple_ircv3_vendor_tags_are_namespaced); |
| |
697 |
| |
698 g_test_add_func("/ircv3/parser/special-mode-1", |
| |
699 test_purple_ircv3_special_mode_1); |
| |
700 g_test_add_func("/ircv3/parser/special-mode-2", |
| |
701 test_purple_ircv3_special_mode_2); |
| |
702 |
| |
703 return g_test_run(); |
| |
704 } |