libpurple/protocols/ircv3/tests/test_ircv3_parser.c

changeset 41774
170078e728c0
child 41931
f35eb5adb2e0
equal deleted inserted replaced
41773:c4acd02fdf73 41774:170078e728c0
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 }

mercurial