1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 198;
7
8use XML::RSS;
9use HTML::Entities qw(encode_entities);
10
11sub output_contains
12{
13    local $Test::Builder::Level = $Test::Builder::Level + 1;
14    my ($rss_output, $sub_string, $msg) = @_;
15
16    my $ok = ok (index ($rss_output,
17        $sub_string) >= 0,
18        $msg
19    );
20    if (! $ok)
21    {
22        diag("Could not find the substring [$sub_string] in:{{{{\n$rss_output\n}}}}\n");
23    }
24    return $ok;
25}
26
27sub contains
28{
29    local $Test::Builder::Level = $Test::Builder::Level + 1;
30    my ($rss, $sub_string, $msg) = @_;
31    return output_contains($rss->as_string(), $sub_string, $msg);
32}
33
34sub not_contains
35{
36    local $Test::Builder::Level = $Test::Builder::Level + 1;
37    my ($rss, $sub_string, $msg) = @_;
38    ok ((index ($rss->as_string(),
39        $sub_string) < 0),
40        $msg
41    );
42}
43
44sub create_rss_1
45{
46    my $args = shift;
47
48    my $extra_rss_args = $args->{rss_args} || [];
49    my $rss = XML::RSS->new (version => $args->{version}, @$extra_rss_args);
50    my $image_link = exists($args->{image_link}) ? $args->{image_link} :
51        "http://freshmeat.net/";
52
53    my $extra_image_params = $args->{image_params} || [];
54
55    $rss->channel(
56        title => "freshmeat.net",
57        link  => "http://freshmeat.net",
58        description => "the one-stop-shop for all your Linux software needs",
59        );
60
61    $rss->image(
62        title => "freshmeat.net",
63        url   => "0",
64        link  => $image_link,
65        @{$extra_image_params},
66        );
67
68    $rss->add_item(
69        title => "GTKeyboard 0.85",
70        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
71        );
72
73    return $rss;
74}
75
76
77sub create_no_image_rss
78{
79    my $args = shift;
80    my $rss = XML::RSS->new (version => $args->{version});
81
82    $rss->channel(
83        title => "freshmeat.net",
84        link  => "http://freshmeat.net",
85        description => "the one-stop-shop for all your Linux software needs",
86        );
87
88    $rss->add_item(
89        title => "GTKeyboard 0.85",
90        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
91        );
92
93    return $rss;
94}
95
96sub create_item_with_0_rss
97{
98    my $args = shift;
99    my $rss = XML::RSS->new (version => $args->{version});
100    my $image_link = exists($args->{image_link}) ? $args->{image_link} :
101        "http://freshmeat.net/";
102
103    my $extra_image_params = $args->{image_params} || [];
104    my $extra_item_params = $args->{item_params} || [];
105
106    $rss->channel(
107        title => "freshmeat.net",
108        link  => "http://freshmeat.net",
109        description => "the one-stop-shop for all your Linux software needs",
110        );
111
112    $rss->image(
113        title => "freshmeat.net",
114        url   => "0",
115        link  => $image_link,
116        @{$extra_image_params},
117        );
118
119    $rss->add_item(
120        title => "0",
121        link  => "http://rss.mytld/",
122        @{$extra_item_params},
123        );
124
125    return $rss;
126}
127
128sub create_textinput_with_0_rss
129{
130    my $args = shift;
131    my $rss = XML::RSS->new (version => $args->{version});
132    my $image_link = exists($args->{image_link}) ? $args->{image_link} :
133        "http://freshmeat.net/";
134
135    my $extra_image_params = $args->{image_params} || [];
136    my $extra_item_params = $args->{item_params} || [];
137    my $extra_textinput_params = $args->{textinput_params} || [];
138
139    $rss->channel(
140        title => "freshmeat.net",
141        link  => "http://freshmeat.net",
142        description => "the one-stop-shop for all your Linux software needs",
143        );
144
145    $rss->image(
146        title => "freshmeat.net",
147        url   => "0",
148        link  => $image_link,
149        @{$extra_image_params},
150        );
151
152    $rss->add_item(
153        title => "0",
154        link  => "http://rss.mytld/",
155        @{$extra_item_params},
156        );
157
158    $rss->textinput(
159        (map { $_ => 0 } (qw(link title description name))),
160        @{$extra_textinput_params},
161    );
162
163    return $rss;
164}
165
166sub create_channel_rss
167{
168    my $args = shift;
169    my $rss = XML::RSS->new (version => $args->{version});
170
171    my $extra_channel_params = $args->{channel_params} || [];
172    my @build_date =
173        ($args->{version} eq "2.0" && !$args->{omit_date}) ?
174            (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) :
175            ();
176
177    $rss->channel(
178        title => "freshmeat.net",
179        link  => "http://freshmeat.net",
180        description => "Linux software",
181        @build_date,
182        @{$extra_channel_params},
183        );
184
185    $rss->add_item(
186        title => "GTKeyboard 0.85",
187        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
188        );
189
190    return $rss;
191}
192
193sub create_skipHours_rss
194{
195    my $args = shift;
196    my $rss = XML::RSS->new (version => $args->{version});
197
198    my $extra_channel_params = $args->{channel_params} || [];
199    my $extra_skipHours_params = $args->{skipHours_params} || [];
200    my @build_date =
201        ($args->{version} eq "2.0" && !$args->{omit_date}) ?
202            (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) :
203            ();
204
205    $rss->channel(
206        title => "freshmeat.net",
207        link  => "http://freshmeat.net",
208        description => "Linux software",
209        @build_date,
210        @{$extra_channel_params},
211        );
212
213    $rss->add_item(
214        title => "GTKeyboard 0.85",
215        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
216        );
217
218    $rss->skipHours(@{$extra_skipHours_params});
219
220    return $rss;
221}
222
223sub create_skipDays_rss
224{
225    my $args = shift;
226    my $rss = XML::RSS->new (version => $args->{version});
227
228    my $extra_channel_params = $args->{channel_params} || [];
229    my $extra_skipDays_params = $args->{skipDays_params} || [];
230    my @build_date =
231        ($args->{version} eq "2.0" && !$args->{omit_date}) ?
232            (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) :
233            ();
234
235    $rss->channel(
236        title => "freshmeat.net",
237        link  => "http://freshmeat.net",
238        description => "Linux software",
239        @build_date,
240        @{$extra_channel_params},
241        );
242
243    $rss->add_item(
244        title => "GTKeyboard 0.85",
245        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
246        );
247
248    $rss->skipDays(@{$extra_skipDays_params});
249
250    return $rss;
251}
252
253sub create_rss_with_image_w_undef_link
254{
255    my $args = shift;
256    my $rss = XML::RSS->new (version => $args->{version});
257
258    my $extra_image_params = $args->{image_params} || [];
259
260    $rss->channel(
261        title => "freshmeat.net",
262        link  => "http://freshmeat.net",
263        description => "the one-stop-shop for all your Linux software needs",
264        );
265
266    $rss->image(
267        title => "freshmeat.net",
268        url   => "0",
269        @{$extra_image_params},
270        );
271
272    $rss->add_item(
273        title => "GTKeyboard 0.85",
274        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
275        );
276
277    return $rss;
278}
279
280sub create_item_rss
281{
282    my $args = shift;
283    my $rss = XML::RSS->new (version => $args->{version});
284
285    my $extra_item_params = $args->{item_params} || [];
286
287    $rss->channel(
288        title => "freshmeat.net",
289        link  => "http://freshmeat.net",
290        description => "the one-stop-shop for all your Linux software needs",
291        );
292
293    $rss->add_item(
294        title => "Freecell Solver",
295        link  => "http://fc-solve.berlios.de/",
296        @$extra_item_params,
297        );
298
299    return $rss;
300}
301
302sub create_rss_without_item
303{
304    my $args = shift;
305    my $rss = XML::RSS->new (version => $args->{version});
306
307    $rss->channel(
308        title => "freshmeat.net",
309        link  => "http://freshmeat.net",
310        description => "the one-stop-shop for all your Linux software needs",
311        );
312
313    return $rss;
314}
315
316{
317    my $rss = create_no_image_rss({version => "0.9"});
318    # TEST
319    not_contains($rss, "<image>",
320        "0.9 - if an image was not specified it isn't there."
321    );
322}
323
324{
325    my $rss = create_no_image_rss({version => "0.91"});
326    # TEST
327    not_contains($rss, "<image>",
328        "0.91 - if an image was not specified it isn't there."
329    );
330}
331
332{
333    my $rss = create_no_image_rss({version => "1.0"});
334    # TEST
335    not_contains($rss, "<image rdf:about=\"",
336        "1.0 - if an image was not specified it isn't there."
337    );
338    # TEST
339    not_contains($rss, "<image rdf:resource=\"",
340        "1.0 - if an image was not specified it isn't there."
341    );
342
343}
344
345{
346    my $rss = create_no_image_rss({version => "2.0"});
347    # TEST
348    not_contains($rss, "<image>",
349        "1.0 - if an image was not specified it isn't there."
350    );
351}
352
353{
354    my $rss = create_rss_1({version => "0.9"});
355    # TEST
356    ok ($rss->as_string =~ m{<image>.*?<title>freshmeat.net</title>.*?<url>0</url>.*?<link>http://freshmeat.net/</link>.*?</image>}s,
357         "Checking for image in RSS 0.9");
358}
359
360{
361    my $rss = create_rss_1({version => "0.91"});
362    # TEST
363    ok ($rss->as_string =~ m{<image>.*?<title>freshmeat.net</title>.*?<url>0</url>.*?<link>http://freshmeat.net/</link>.*?</image>}s,
364         "Checking for image in RSS 0.9.1");
365}
366
367{
368    my $rss = create_rss_1({version => "1.0"});
369    # TEST
370    ok ($rss->as_string =~ m{<image rdf:about="0">.*?<title>freshmeat.net</title>.*?<url>0</url>.*?<link>http://freshmeat.net/</link>.*?</image>}s,
371         "Checking for image in RSS 1.0");
372    # TEST
373    contains ($rss,
374        "</items>\n<image rdf:resource=\"0\" />\n",
375        "1.0 - contains image rdf:resource."
376    );
377}
378
379{
380    my $rss = create_rss_1({version => "2.0"});
381    # TEST
382    ok ($rss->as_string =~ m{<image>.*?<title>freshmeat.net</title>.*?<url>0</url>.*?<link>http://freshmeat.net/</link>.*?</image>}s,
383         "Checking for image in RSS 2.0");
384}
385
386{
387    my $rss = create_rss_1({version => "0.9", image_link => "0",});
388    # TEST
389    ok (index($rss->as_string(),
390            "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n<link>0</link>\n</image>\n") >= 0,
391        "Testing for link == 0 appearance in RSS 0.9"
392    );
393}
394
395{
396    my $version = "0.91";
397    my $rss = create_rss_1({version => $version, image_link => "0",});
398    # TEST
399    ok (index($rss->as_string(),
400            "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n<link>0</link>\n</image>\n") >= 0,
401        "Testing for link == 0 appearance in RSS $version"
402    );
403}
404
405{
406    my $version = "1.0";
407    my $rss = create_rss_1({version => $version, image_link => "0",});
408    # TEST
409    ok (index($rss->as_string(),
410            qq{<image rdf:about="0">\n<title>freshmeat.net</title>\n<url>0</url>\n<link>0</link>\n</image>\n}) >= 0,
411        "Testing for link == 0 appearance in RSS $version"
412    );
413}
414
415{
416    my $version = "2.0";
417    my $rss = create_rss_1({version => $version, image_link => "0",});
418    # TEST
419    ok (index($rss->as_string(),
420            qq{<image>\n<title>freshmeat.net</title>\n<url>0</url>\n<link>0</link>\n</image>\n}) >= 0,
421        "Testing for link == 0 appearance in RSS $version"
422    );
423}
424
425{
426    my $version = "0.91";
427    my $rss = create_rss_1({
428            version => $version,
429            image_params => [width => 0, height => 0, description => 0],
430        }
431    );
432    # TEST
433    contains($rss,
434            "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n"
435            . "<link>http://freshmeat.net/</link>\n"
436            . "<width>0</width>\n<height>0</height>\n"
437            . "<description>0</description>\n</image>\n",
438        "Testing for width, height, description == 0 appearance in RSS $version"
439    );
440}
441
442{
443    my $rss = create_rss_1({
444            version => "2.0",
445            image_params => [width => 0, height => 0, description => 0],
446        }
447    );
448    # TEST
449    contains($rss,
450            "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n"
451            . "<link>http://freshmeat.net/</link>\n"
452            . "<width>0</width>\n<height>0</height>\n"
453            . "<description>0</description>\n</image>\n",
454        "2.0 - all(width, height, description) == 0 appearance"
455    );
456}
457
458{
459    my $rss = create_item_with_0_rss({version => "0.9"});
460    # TEST
461    contains(
462        $rss,
463        "<item>\n<title>0</title>\n<link>http://rss.mytld/</link>\n</item>",
464        "0.9 - item/title == 0",
465    );
466}
467
468{
469    my $rss = create_item_with_0_rss({version => "0.91",
470            item_params => [description => "Hello There"],
471        });
472    # TEST
473    contains(
474        $rss,
475        "<item>\n<title>0</title>\n<link>http://rss.mytld/</link>\n<description>Hello There</description>\n</item>",
476        "0.9.1 - item/title == 0",
477    );
478}
479
480{
481    my $rss = create_item_with_0_rss({version => "0.91",
482            item_params => [description => "0"],
483        });
484    # TEST
485    contains(
486        $rss,
487        "<item>\n<title>0</title>\n<link>http://rss.mytld/</link>\n<description>0</description>\n</item>",
488        "0.9.1 - item/title == 0 && item/description == 0",
489    );
490}
491
492{
493    my $rss = create_item_with_0_rss({version => "1.0",
494            item_params => [description => "Hello There", about => "Yowza"],
495        });
496    # TEST
497    contains(
498        $rss,
499        "<item rdf:about=\"Yowza\">\n<title>0</title>\n<link>http://rss.mytld/</link>\n<description>Hello There</description>\n</item>",
500        "1.0 - item/title == 0",
501    );
502}
503
504{
505    my $rss = create_item_with_0_rss({version => "1.0",
506            item_params => [description => "0", about => "Yowza"],
507        });
508    # TEST
509    contains(
510        $rss,
511        "<item rdf:about=\"Yowza\">\n<title>0</title>\n<link>http://rss.mytld/</link>\n<description>0</description>\n</item>",
512        "1.0 - item/title == 0 && item/description == 0",
513    );
514}
515# TODO : Test the dc: items.
516
517{
518    my @subs = (qw(title link description author category comments pubDate));
519    my $rss = create_item_with_0_rss({version => "2.0",
520            item_params =>
521            [
522                map { $_ => 0 } @subs
523            ],
524        }
525    );
526
527    # TEST
528    contains(
529        $rss,
530        ("<item>\n"
531        . join("", map { "<$_>0</$_>\n" } @subs)
532        . "</item>"),
533        "2.0 - item/* == 0 - 1",
534    );
535}
536
537{
538    my $rss = create_item_with_0_rss({version => "2.0",
539            item_params =>
540            [
541                title => "Foo&Bar",
542                link => "http://www.mytld/",
543                permaLink => "0",
544            ],
545        }
546    );
547
548    # TEST
549    contains(
550        $rss,
551        ("<item>\n" .
552         "<title>Foo&#x26;Bar</title>\n" .
553         "<link>http://www.mytld/</link>\n" .
554         "<guid isPermaLink=\"true\">0</guid>\n" .
555         "</item>"
556         ),
557        "2.0 - item/permaLink == 0",
558    );
559}
560
561{
562    my $rss = create_item_with_0_rss({version => "2.0",
563            item_params =>
564            [
565                title => "Foo&Bar",
566                link => "http://www.mytld/",
567                guid => "0",
568            ],
569        }
570    );
571
572    # TEST
573    contains(
574        $rss,
575        ("<item>\n" .
576         "<title>Foo&#x26;Bar</title>\n" .
577         "<link>http://www.mytld/</link>\n" .
578         "<guid isPermaLink=\"false\">0</guid>\n" .
579         "</item>"
580         ),
581        "2.0 - item/guid == 0",
582    );
583}
584
585{
586    # TEST:$num_iters=4;
587    foreach my $s (
588        ["Hercules", "http://www.hercules.tld/",],
589        ["0", "http://www.hercules.tld/",],
590        ["Hercules", "0",],
591        ["0", "0",],
592        )
593    {
594        my $rss = create_item_with_0_rss({version => "2.0",
595                item_params =>
596                [
597                    title => "Foo&Bar",
598                    link => "http://www.mytld/",
599                    source => $s->[0],
600                    sourceUrl => $s->[1],
601                ],
602            }
603        );
604
605        # TEST*$num_iters
606        contains(
607            $rss,
608            ("<item>\n" .
609             "<title>Foo&#x26;Bar</title>\n" .
610             "<link>http://www.mytld/</link>\n" .
611             "<source url=\"$s->[1]\">$s->[0]</source>\n" .
612             "</item>"
613             ),
614            "2.0 - item - source = $s->[0] sourceUrl = $s->[1]",
615        );
616    }
617}
618
619{
620    my $rss = create_no_image_rss({version => "0.9"});
621    # TEST
622    not_contains($rss, "<textinput>",
623        "0.9 - if a textinput was not specified it isn't there."
624    );
625}
626
627{
628    my $rss = create_textinput_with_0_rss({version => "0.9"});
629    # TEST
630    contains(
631        $rss,
632        ("<textinput>\n" . join("", map {"<$_>0</$_>\n"} (qw(title description name link))) . "</textinput>\n"),
633        "0.9 - textinput/link == 0",
634    );
635}
636
637{
638    my $rss = create_no_image_rss({version => "0.91"});
639    # TEST
640    not_contains($rss, "<textinput>",
641        "0.9.1 - if a textinput was not specified it isn't there."
642    );
643}
644
645{
646    my $rss = create_textinput_with_0_rss({version => "0.91"});
647    # TEST
648    contains(
649        $rss,
650        ("<textinput>\n" . join("", map {"<$_>0</$_>\n"} (qw(title description name link))) . "</textinput>\n"),
651        "0.9.1 - textinput/link == 0",
652    );
653}
654
655{
656    my $rss = create_no_image_rss({version => "1.0"});
657    # TEST
658    not_contains($rss, "<textinput rdf:about=",
659        "1.0 - if a textinput was not specified it isn't there."
660    );
661    # TEST
662    not_contains($rss, "<textinput rdf:resource=",
663        "1.0 - if a textinput was not specified it isn't there."
664    );
665
666}
667
668{
669    my $rss = create_textinput_with_0_rss({version => "1.0"});
670    # TEST
671    contains(
672        $rss,
673        ("<textinput rdf:about=\"0\">\n" . join("", map {"<$_>0</$_>\n"} (qw(title description name link))) . "</textinput>\n"),
674        "1.0 - textinput/link == 0",
675    );
676    # TEST
677    contains(
678        $rss,
679        "<textinput rdf:resource=\"0\" />\n</channel>\n",
680        "1.0 - textinput/link == 0 and textinput rdf:resource",
681    );
682}
683
684
685{
686    my $rss = create_no_image_rss({version => "2.0"});
687    # TEST
688    not_contains($rss, "<textInput>",
689        "2.0 - if a textinput was not specified it isn't there."
690    );
691}
692
693{
694    my $rss = create_textinput_with_0_rss({version => "2.0"});
695    # TEST
696    contains(
697        $rss,
698        ("<textInput>\n" . join("", map {"<$_>0</$_>\n"} (qw(title description name link))) . "</textInput>\n"),
699        "2.0 - textinput/link == 0",
700    );
701}
702
703{
704    my $rss = create_channel_rss({version => "0.91"});
705    # TEST
706    contains($rss, "<channel>\n" .
707        "<title>freshmeat.net</title>\n" .
708        "<link>http://freshmeat.net</link>\n" .
709        "<description>Linux software</description>\n" .
710        "\n" .
711        "<item>\n",
712        "0.9.1 - if a channel/dc/language was not specified it isn't there."
713    );
714}
715
716{
717    my $rss = create_channel_rss({
718            version => "0.91",
719            channel_params => [dc => { language => "0",},],
720        });
721    # TEST
722    contains($rss, "<channel>\n" .
723        "<title>freshmeat.net</title>\n" .
724        "<link>http://freshmeat.net</link>\n" .
725        "<description>Linux software</description>\n" .
726        "<language>0</language>\n" .
727        "\n" .
728        "<item>\n",
729        "0.9.1 - channel/dc/language == 0"
730    );
731}
732
733{
734    my $rss = create_channel_rss({
735            version => "0.91",
736            channel_params => [language => "0",],
737        });
738    # TEST
739    contains($rss, "<channel>\n" .
740        "<title>freshmeat.net</title>\n" .
741        "<link>http://freshmeat.net</link>\n" .
742        "<description>Linux software</description>\n" .
743        "<language>0</language>\n" .
744        "\n" .
745        "<item>\n",
746        "0.9.1 - channel/language == 0"
747    );
748}
749
750{
751    my $rss = create_channel_rss({version => "1.0"});
752    # TEST
753    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
754        "<title>freshmeat.net</title>\n" .
755        "<link>http://freshmeat.net</link>\n" .
756        "<description>Linux software</description>\n" .
757        "<items>\n",
758        "1.0 - if a channel/dc/language was not specified it isn't there."
759    );
760}
761
762{
763    my $rss = create_channel_rss({
764            version => "1.0",
765            channel_params => [dc => { language => "0",},],
766        });
767    # TEST
768    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
769        "<title>freshmeat.net</title>\n" .
770        "<link>http://freshmeat.net</link>\n" .
771        "<description>Linux software</description>\n" .
772        "<dc:language>0</dc:language>\n" .
773        "<items>\n",
774        "1.0 - channel/dc/language == 0"
775    );
776}
777
778{
779    my $rss = create_channel_rss({
780            version => "1.0",
781            channel_params => [language => "0",],
782        });
783    # TEST
784    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
785        "<title>freshmeat.net</title>\n" .
786        "<link>http://freshmeat.net</link>\n" .
787        "<description>Linux software</description>\n" .
788        "<dc:language>0</dc:language>\n" .
789        "<items>\n",
790        "1.0 - channel/language == 0"
791    );
792}
793
794
795{
796    my $rss = create_channel_rss({version => "2.0"});
797    # TEST
798    contains($rss, "<channel>\n" .
799        "<title>freshmeat.net</title>\n" .
800        "<link>http://freshmeat.net</link>\n" .
801        "<description>Linux software</description>\n" .
802        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
803        "\n" .
804        "<item>\n",
805        "2.0 - if a channel/dc/language was not specified it isn't there."
806    );
807}
808
809{
810    my $rss = create_channel_rss({
811            version => "2.0",
812            channel_params => [dc => { language => "0",},],
813        });
814    # TEST
815    contains($rss, "<channel>\n" .
816        "<title>freshmeat.net</title>\n" .
817        "<link>http://freshmeat.net</link>\n" .
818        "<description>Linux software</description>\n" .
819        "<language>0</language>\n" .
820        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
821        "\n" .
822        "<item>\n",
823        "2.0 - channel/dc/language == 0"
824    );
825}
826
827{
828    my $rss = create_channel_rss({
829            version => "2.0",
830            channel_params => [language => "0",],
831        });
832    # TEST
833    contains($rss, "<channel>\n" .
834        "<title>freshmeat.net</title>\n" .
835        "<link>http://freshmeat.net</link>\n" .
836        "<description>Linux software</description>\n" .
837        "<language>0</language>\n" .
838        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
839        "\n" .
840        "<item>\n",
841        "2.0 - channel/language == 0"
842    );
843}
844
845{
846    my $rss = create_channel_rss({
847            version => "0.91",
848            channel_params => [rating => "0",],
849        });
850    # TEST
851    contains($rss, "<channel>\n" .
852        "<title>freshmeat.net</title>\n" .
853        "<link>http://freshmeat.net</link>\n" .
854        "<description>Linux software</description>\n" .
855        "<rating>0</rating>\n" .
856        "\n" .
857        "<item>\n",
858        "0.9.1 - channel/rating == 0"
859    );
860}
861
862{
863    my $rss = create_channel_rss({
864            version => "0.91",
865            channel_params => [rating => "Hello", dc => {rights => "0"},],
866        });
867    # TEST
868    contains($rss, "<channel>\n" .
869        "<title>freshmeat.net</title>\n" .
870        "<link>http://freshmeat.net</link>\n" .
871        "<description>Linux software</description>\n" .
872        "<rating>Hello</rating>\n" .
873        "<copyright>0</copyright>\n" .
874        "\n" .
875        "<item>\n",
876        "0.9.1 - channel/dc/copyright == 0"
877    );
878}
879
880
881{
882    my $rss = create_channel_rss({
883            version => "0.91",
884            channel_params => [rating => "Hello", copyright => "0",],
885        });
886    # TEST
887    contains($rss, "<channel>\n" .
888        "<title>freshmeat.net</title>\n" .
889        "<link>http://freshmeat.net</link>\n" .
890        "<description>Linux software</description>\n" .
891        "<rating>Hello</rating>\n" .
892        "<copyright>0</copyright>\n" .
893        "\n" .
894        "<item>\n",
895        "0.9.1 - channel/copyright == 0"
896    );
897}
898
899{
900    my $rss = create_channel_rss({
901            version => "2.0",
902            channel_params => [dc => {rights => "0"},],
903        });
904    # TEST
905    contains($rss, "<channel>\n" .
906        "<title>freshmeat.net</title>\n" .
907        "<link>http://freshmeat.net</link>\n" .
908        "<description>Linux software</description>\n" .
909        "<copyright>0</copyright>\n" .
910        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
911        "\n" .
912        "<item>\n",
913        "2.0 - channel/dc/rights == 0"
914    );
915}
916
917{
918    my $rss = create_channel_rss({
919            version => "2.0",
920            channel_params => [copyright=> "0",],
921        });
922    # TEST
923    contains($rss, "<channel>\n" .
924        "<title>freshmeat.net</title>\n" .
925        "<link>http://freshmeat.net</link>\n" .
926        "<description>Linux software</description>\n" .
927        "<copyright>0</copyright>\n" .
928        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
929        "\n" .
930        "<item>\n",
931        "2.0 - channel/copyright == 0"
932    );
933}
934
935{
936    my $rss = create_channel_rss({
937            version => "0.91",
938            channel_params =>
939            [rating => "Hello", copyright => "Martha",docs => "0",],
940        });
941    # TEST
942    contains($rss, "<channel>\n" .
943        "<title>freshmeat.net</title>\n" .
944        "<link>http://freshmeat.net</link>\n" .
945        "<description>Linux software</description>\n" .
946        "<rating>Hello</rating>\n" .
947        "<copyright>Martha</copyright>\n" .
948        "<docs>0</docs>\n" .
949        "\n" .
950        "<item>\n",
951        "0.9.1 - channel/docs == 0"
952    );
953}
954
955{
956    my $rss = create_channel_rss({
957            version => "2.0",
958            channel_params => [copyright => "Martha", docs => "0",],
959        });
960    # TEST
961    contains($rss, "<channel>\n" .
962        "<title>freshmeat.net</title>\n" .
963        "<link>http://freshmeat.net</link>\n" .
964        "<description>Linux software</description>\n" .
965        "<copyright>Martha</copyright>\n" .
966        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
967        "<docs>0</docs>\n" .
968        "\n" .
969        "<item>\n",
970        "2.0 - channel/docs == 0"
971    );
972}
973
974{
975    my $rss = create_channel_rss({
976            version => "0.91",
977            channel_params =>
978            [rating => "Hello", copyright => "Martha",
979            docs => "MyDr. docs",dc => {publisher => 0}],
980        });
981    # TEST
982    contains($rss, "<channel>\n" .
983        "<title>freshmeat.net</title>\n" .
984        "<link>http://freshmeat.net</link>\n" .
985        "<description>Linux software</description>\n" .
986        "<rating>Hello</rating>\n" .
987        "<copyright>Martha</copyright>\n" .
988        "<docs>MyDr. docs</docs>\n" .
989        "<managingEditor>0</managingEditor>\n" .
990        "\n" .
991        "<item>\n",
992        "0.9.1 - channel/dc/publisher == 0"
993    );
994}
995
996{
997    my $rss = create_channel_rss({
998            version => "0.91",
999            channel_params =>
1000            [rating => "Hello", copyright => "Martha",
1001            docs => "MyDr. docs",managingEditor => 0],
1002        });
1003    # TEST
1004    contains($rss, "<channel>\n" .
1005        "<title>freshmeat.net</title>\n" .
1006        "<link>http://freshmeat.net</link>\n" .
1007        "<description>Linux software</description>\n" .
1008        "<rating>Hello</rating>\n" .
1009        "<copyright>Martha</copyright>\n" .
1010        "<docs>MyDr. docs</docs>\n" .
1011        "<managingEditor>0</managingEditor>\n" .
1012        "\n" .
1013        "<item>\n",
1014        "0.9.1 - channel/managingEditor == 0"
1015    );
1016}
1017
1018{
1019    my $rss = create_channel_rss({
1020            version => "2.0",
1021            channel_params =>
1022            [copyright => "Martha",
1023            docs => "MyDr. docs",managingEditor => 0],
1024        });
1025    # TEST
1026    contains($rss, "<channel>\n" .
1027        "<title>freshmeat.net</title>\n" .
1028        "<link>http://freshmeat.net</link>\n" .
1029        "<description>Linux software</description>\n" .
1030        "<copyright>Martha</copyright>\n" .
1031        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1032        "<docs>MyDr. docs</docs>\n" .
1033        "<managingEditor>0</managingEditor>\n" .
1034        "\n" .
1035        "<item>\n",
1036        "2.0 - channel/managingEditor == 0"
1037    );
1038}
1039
1040{
1041    my $rss = create_channel_rss({
1042            version => "2.0",
1043            channel_params =>
1044            [copyright => "Martha", docs => "MyDr. docs",
1045            dc => {publisher => 0}],
1046        });
1047    # TEST
1048    contains($rss, "<channel>\n" .
1049        "<title>freshmeat.net</title>\n" .
1050        "<link>http://freshmeat.net</link>\n" .
1051        "<description>Linux software</description>\n" .
1052        "<copyright>Martha</copyright>\n" .
1053        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1054        "<docs>MyDr. docs</docs>\n" .
1055        "<managingEditor>0</managingEditor>\n" .
1056        "\n" .
1057        "<item>\n",
1058        "2.0 - channel/dc/publisher == 0"
1059    );
1060}
1061
1062{
1063    my $rss = create_channel_rss({
1064            version => "1.0",
1065            channel_params =>
1066            [copyright => "Martha", dc => {publisher => 0}],
1067        });
1068    # TEST
1069    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1070        "<title>freshmeat.net</title>\n" .
1071        "<link>http://freshmeat.net</link>\n" .
1072        "<description>Linux software</description>\n" .
1073        "<dc:rights>Martha</dc:rights>\n" .
1074        "<dc:publisher>0</dc:publisher>\n" .
1075        "<items>\n",
1076        "1.0 - channel/dc/publisher == 0"
1077    );
1078}
1079
1080{
1081    # Here we create an RSS 2.0 object and render it as 1.0 to get the
1082    # "managingEditor" field acknowledged.
1083    my $rss = create_channel_rss({
1084            version => "2.0",
1085            channel_params =>
1086            [copyright => "Martha", managingEditor => 0,],
1087            omit_date => 1,
1088        });
1089    $rss->{output} = "1.0";
1090    # TEST
1091    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1092        "<title>freshmeat.net</title>\n" .
1093        "<link>http://freshmeat.net</link>\n" .
1094        "<description>Linux software</description>\n" .
1095        "<dc:rights>Martha</dc:rights>\n" .
1096        "<dc:publisher>0</dc:publisher>\n" .
1097        "<items>\n",
1098        "1.0 - channel/managingEditor == 0"
1099    );
1100}
1101
1102{
1103    my $rss = create_channel_rss({
1104            version => "0.91",
1105            channel_params =>
1106            [rating => "Hello", copyright => "Martha",
1107            docs => "MyDr. docs",dc => {creator => 0}],
1108        });
1109    # TEST
1110    contains($rss, "<channel>\n" .
1111        "<title>freshmeat.net</title>\n" .
1112        "<link>http://freshmeat.net</link>\n" .
1113        "<description>Linux software</description>\n" .
1114        "<rating>Hello</rating>\n" .
1115        "<copyright>Martha</copyright>\n" .
1116        "<docs>MyDr. docs</docs>\n" .
1117        "<webMaster>0</webMaster>\n" .
1118        "\n" .
1119        "<item>\n",
1120        "0.9.1 - channel/dc/publisher == 0"
1121    );
1122}
1123
1124{
1125    my $rss = create_channel_rss({
1126            version => "0.91",
1127            channel_params =>
1128            [rating => "Hello", copyright => "Martha",
1129            docs => "MyDr. docs",webMaster => 0],
1130        });
1131    # TEST
1132    contains($rss, "<channel>\n" .
1133        "<title>freshmeat.net</title>\n" .
1134        "<link>http://freshmeat.net</link>\n" .
1135        "<description>Linux software</description>\n" .
1136        "<rating>Hello</rating>\n" .
1137        "<copyright>Martha</copyright>\n" .
1138        "<docs>MyDr. docs</docs>\n" .
1139        "<webMaster>0</webMaster>\n" .
1140        "\n" .
1141        "<item>\n",
1142        "0.9.1 - channel/webMaster == 0"
1143    );
1144}
1145
1146{
1147    my $rss = create_channel_rss({
1148            version => "1.0",
1149            channel_params =>
1150            [copyright => "Martha", dc => {creator => 0}],
1151        });
1152    # TEST
1153    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1154        "<title>freshmeat.net</title>\n" .
1155        "<link>http://freshmeat.net</link>\n" .
1156        "<description>Linux software</description>\n" .
1157        "<dc:rights>Martha</dc:rights>\n" .
1158        "<dc:creator>0</dc:creator>\n" .
1159        "<items>\n",
1160        "1.0 - channel/dc/creator == 0"
1161    );
1162}
1163
1164{
1165    # Here we create an RSS 2.0 object and render it as 1.0 to get the
1166    # "managingEditor" field acknowledged.
1167    my $rss = create_channel_rss({
1168            version => "2.0",
1169            channel_params =>
1170            [copyright => "Martha", webMaster => 0,],
1171            omit_date => 1,
1172        });
1173    $rss->{output} = "1.0";
1174    # TEST
1175    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1176        "<title>freshmeat.net</title>\n" .
1177        "<link>http://freshmeat.net</link>\n" .
1178        "<description>Linux software</description>\n" .
1179        "<dc:rights>Martha</dc:rights>\n" .
1180        "<dc:creator>0</dc:creator>\n" .
1181        "<items>\n",
1182        "1.0 - channel/managingEditor == 0"
1183    );
1184}
1185
1186{
1187    my $rss = create_channel_rss({
1188            version => "2.0",
1189            channel_params =>
1190            [copyright => "Martha",
1191            docs => "MyDr. docs",webMaster => 0],
1192        });
1193    # TEST
1194    contains($rss, "<channel>\n" .
1195        "<title>freshmeat.net</title>\n" .
1196        "<link>http://freshmeat.net</link>\n" .
1197        "<description>Linux software</description>\n" .
1198        "<copyright>Martha</copyright>\n" .
1199        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1200        "<docs>MyDr. docs</docs>\n" .
1201        "<webMaster>0</webMaster>\n" .
1202        "\n" .
1203        "<item>\n",
1204        "2.0 - channel/webMaster == 0"
1205    );
1206}
1207
1208{
1209    my $rss = create_channel_rss({
1210            version => "2.0",
1211            channel_params =>
1212            [copyright => "Martha", docs => "MyDr. docs",
1213            dc => {creator => 0}],
1214        });
1215    # TEST
1216    contains($rss, "<channel>\n" .
1217        "<title>freshmeat.net</title>\n" .
1218        "<link>http://freshmeat.net</link>\n" .
1219        "<description>Linux software</description>\n" .
1220        "<copyright>Martha</copyright>\n" .
1221        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1222        "<docs>MyDr. docs</docs>\n" .
1223        "<webMaster>0</webMaster>\n" .
1224        "\n" .
1225        "<item>\n",
1226        "2.0 - channel/dc/creator == 0"
1227    );
1228}
1229
1230{
1231    my $rss = create_no_image_rss({version => "0.91"});
1232    # TEST
1233    not_contains($rss, "<skipHours>",
1234        "0.91 - if skipHours was not specified it isn't there."
1235    );
1236}
1237
1238{
1239    my $rss = create_skipHours_rss({
1240            version => "0.91",
1241            skipHours_params => [ hour => "0" ],
1242        });
1243    # TEST
1244    contains($rss, "<skipHours>\n<hour>0</hour>\n</skipHours>\n",
1245        "0.91 - skipHours/hours == 0"
1246    );
1247}
1248
1249{
1250    my $rss = create_no_image_rss({version => "2.0"});
1251    # TEST
1252    not_contains($rss, "<skipHours>",
1253        "2.0 - if skipHours was not specified it isn't there."
1254    );
1255}
1256
1257{
1258    my $rss = create_skipHours_rss({
1259            version => "2.0",
1260            skipHours_params => [ hour => "0" ],
1261        });
1262    # TEST
1263    contains($rss, "<skipHours>\n<hour>0</hour>\n</skipHours>\n",
1264        "2.0 - skipHours/hour == 0"
1265    );
1266}
1267
1268{
1269    my $rss = create_no_image_rss({version => "0.91"});
1270    # TEST
1271    not_contains($rss, "<skipDays>",
1272        "0.91 - if skipDays was not specified it isn't there."
1273    );
1274}
1275
1276{
1277    my $rss = create_skipDays_rss({
1278            version => "0.91",
1279            skipDays_params => [ day => "0" ],
1280        });
1281    # TEST
1282    contains($rss, "<skipDays>\n<day>0</day>\n</skipDays>\n",
1283        "0.91 - skipDays/days == 0"
1284    );
1285}
1286
1287{
1288    my $rss = create_no_image_rss({version => "2.0"});
1289    # TEST
1290    not_contains($rss, "<skipDays>",
1291        "2.0 - if skipDays was not specified it isn't there."
1292    );
1293}
1294
1295{
1296    my $rss = create_skipDays_rss({
1297            version => "2.0",
1298            skipDays_params => [ day => "0" ],
1299        });
1300    # TEST
1301    contains($rss, "<skipDays>\n<day>0</day>\n</skipDays>\n",
1302        "2.0 - skipDays/day == 0"
1303    );
1304}
1305
1306{
1307    my $rss = create_channel_rss({
1308            version => "1.0",
1309        });
1310    # TEST
1311    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1312        "<title>freshmeat.net</title>\n" .
1313        "<link>http://freshmeat.net</link>\n" .
1314        "<description>Linux software</description>\n" .
1315        "<items>\n",
1316        "1.0 - channel/dc/creator == 0"
1317    );
1318}
1319
1320{
1321    my $rss = create_channel_rss({
1322            version => "1.0",
1323            channel_params =>
1324            [copyright => 0,],
1325        });
1326    # TEST
1327    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1328        "<title>freshmeat.net</title>\n" .
1329        "<link>http://freshmeat.net</link>\n" .
1330        "<description>Linux software</description>\n" .
1331        "<dc:rights>0</dc:rights>\n" .
1332        "<items>\n",
1333        "1.0 - channel/copyright == 0"
1334    );
1335}
1336
1337{
1338    my $rss = create_channel_rss({
1339            version => "1.0",
1340            channel_params =>
1341            [dc => { rights => 0},],
1342        });
1343    # TEST
1344    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1345        "<title>freshmeat.net</title>\n" .
1346        "<link>http://freshmeat.net</link>\n" .
1347        "<description>Linux software</description>\n" .
1348        "<dc:rights>0</dc:rights>\n" .
1349        "<items>\n",
1350        "1.0 - channel/dc/rights == 0"
1351    );
1352}
1353
1354{
1355    my $rss = create_channel_rss({
1356            version => "1.0",
1357            channel_params =>
1358            [dc => { title => 0},],
1359        });
1360    # TEST
1361    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1362        "<title>freshmeat.net</title>\n" .
1363        "<link>http://freshmeat.net</link>\n" .
1364        "<description>Linux software</description>\n" .
1365        "<dc:title>0</dc:title>\n" .
1366        "<items>\n",
1367        "1.0 - channel/dc/title == 0"
1368    );
1369}
1370
1371{
1372    my $rss = create_channel_rss({
1373            version => "1.0",
1374            channel_params =>
1375            [syn => { updateBase=> 0},],
1376        });
1377    # TEST
1378    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1379        "<title>freshmeat.net</title>\n" .
1380        "<link>http://freshmeat.net</link>\n" .
1381        "<description>Linux software</description>\n" .
1382        "<syn:updateBase>0</syn:updateBase>\n" .
1383        "<items>\n",
1384        "1.0 - channel/syn/updateBase == 0"
1385    );
1386}
1387
1388{
1389    my $rss = create_rss_1({version => "1.0",
1390            image_params => [ dc => { subject => 0, }]
1391        });
1392    # TEST
1393    contains ($rss,
1394        (qq{<image rdf:about="0">\n<title>freshmeat.net</title>\n} .
1395        qq{<url>0</url>\n<link>http://freshmeat.net/</link>\n} .
1396        qq{<dc:subject>0</dc:subject>\n</image>}),
1397         "1.0 - Checking for image/dc/subject == 0");
1398}
1399
1400{
1401    my $rss = create_item_with_0_rss({version => "1.0",
1402            item_params =>
1403            [
1404                description => "Hello There",
1405                about => "Yowza",
1406                dc => { subject => 0,},
1407            ],
1408        });
1409    # TEST
1410    contains(
1411        $rss,
1412        "<item rdf:about=\"Yowza\">\n<title>0</title>\n<link>http://rss.mytld/</link>\n<description>Hello There</description>\n<dc:subject>0</dc:subject>\n</item>",
1413        "1.0 - item/dc/subject == 0",
1414    );
1415}
1416
1417{
1418    my $rss = create_textinput_with_0_rss({version => "1.0",
1419            textinput_params => [dc => { subject => 0,},],
1420        });
1421    # TEST
1422    contains(
1423        $rss,
1424        ("<textinput rdf:about=\"0\">\n" . join("", map {"<$_>0</$_>\n"} (qw(title description name link dc:subject))) . "</textinput>\n"),
1425        "1.0 - textinput/dc/subject == 0",
1426    );
1427}
1428
1429{
1430    # TEST:$num_fields=3;
1431    foreach my $field (qw(category generator ttl))
1432    {
1433        # TEST:$num_dc=2;
1434        foreach my $dc (1,0)
1435        {
1436            my $rss = create_channel_rss({
1437                    version => "2.0",
1438                    channel_params =>
1439                    [$dc ?
1440                        (dc => {$field => 0 }) :
1441                        ($field => 0)
1442                    ],
1443                });
1444            # TEST*$num_fields*$num_dc
1445            contains($rss, "<channel>\n" .
1446                "<title>freshmeat.net</title>\n" .
1447                "<link>http://freshmeat.net</link>\n" .
1448                "<description>Linux software</description>\n" .
1449                "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1450                "<$field>0</$field>\n" .
1451                "\n" .
1452                "<item>\n",
1453                "2.0 - Testing for fields with an optional dc being 0. (dc=$dc,field=$field)"
1454            );
1455        }
1456    }
1457}
1458
1459{
1460    my $rss = create_channel_rss({
1461            version => "0.91",
1462            channel_params => [pubDate => "</pubDate><hello>There&amp;Everywhere</hello>"],
1463        });
1464    # TEST
1465    contains($rss, "<channel>\n" .
1466        "<title>freshmeat.net</title>\n" .
1467        "<link>http://freshmeat.net</link>\n" .
1468        "<description>Linux software</description>\n" .
1469        "<pubDate>&#x3C;/pubDate&#x3E;&#x3C;hello&#x3E;There&#x26;amp;Everywhere&#x3C;/hello&#x3E;</pubDate>\n" .
1470        "\n" .
1471        "<item>\n",
1472        "0.9.1 - channel/pubDate Markup Injection"
1473    );
1474}
1475
1476{
1477    my $rss = create_channel_rss({
1478            version => "0.91",
1479            channel_params => [lastBuildDate => "</pubDate><hello>There&amp;Everywhere</hello>"],
1480        });
1481    # TEST
1482    contains($rss, "<channel>\n" .
1483        "<title>freshmeat.net</title>\n" .
1484        "<link>http://freshmeat.net</link>\n" .
1485        "<description>Linux software</description>\n" .
1486        "<lastBuildDate>&#x3C;/pubDate&#x3E;&#x3C;hello&#x3E;There&#x26;amp;Everywhere&#x3C;/hello&#x3E;</lastBuildDate>\n" .
1487        "\n" .
1488        "<item>\n",
1489        "0.9.1 - channel/lastBuildDate Markup Injection"
1490    );
1491}
1492
1493{
1494    my $rss = create_channel_rss({
1495        version => "1.0",
1496        channel_params =>
1497        [
1498            dc =>
1499            {
1500                date => "</pubDate><hello>There&amp;Everywhere</hello>"
1501            },
1502        ],
1503    });
1504    # TEST
1505    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1506        "<title>freshmeat.net</title>\n" .
1507        "<link>http://freshmeat.net</link>\n" .
1508        "<description>Linux software</description>\n" .
1509        "<dc:date>&#x3C;/pubDate&#x3E;&#x3C;hello&#x3E;There&#x26;amp;Everywhere&#x3C;/hello&#x3E;</dc:date>\n" .
1510        "<items>\n",
1511        "1.0 - dc/date Markup Injection"
1512    );
1513}
1514
1515{
1516    my $rss = create_channel_rss({version => "2.0",
1517            channel_params => [pubDate => "</pubDate><hello>There&amp;Everywhere</hello>"],
1518            omit_date => 1,
1519        });
1520    # TEST
1521    contains($rss, "<channel>\n" .
1522        "<title>freshmeat.net</title>\n" .
1523        "<link>http://freshmeat.net</link>\n" .
1524        "<description>Linux software</description>\n" .
1525        "<pubDate>&#x3C;/pubDate&#x3E;&#x3C;hello&#x3E;There&#x26;amp;Everywhere&#x3C;/hello&#x3E;</pubDate>\n" .
1526        "\n" .
1527        "<item>\n",
1528        "2.0 - channel/pubDate Markup Injection"
1529    );
1530}
1531
1532{
1533    my $rss = create_channel_rss({version => "2.0",
1534            channel_params => [lastBuildDate => "</pubDate><hello>There&amp;Everywhere</hello>"],
1535            omit_date => 1,
1536        });
1537    # TEST
1538    contains($rss, "<channel>\n" .
1539        "<title>freshmeat.net</title>\n" .
1540        "<link>http://freshmeat.net</link>\n" .
1541        "<description>Linux software</description>\n" .
1542        "<lastBuildDate>&#x3C;/pubDate&#x3E;&#x3C;hello&#x3E;There&#x26;amp;Everywhere&#x3C;/hello&#x3E;</lastBuildDate>\n" .
1543        "\n" .
1544        "<item>\n",
1545        "2.0 - channel/lastBuildDate Markup Injection"
1546    );
1547}
1548
1549{
1550    my $rss = create_rss_with_image_w_undef_link({version => "0.9"});
1551    # TEST
1552    contains ($rss, qq{<image>\n<title>freshmeat.net</title>\n<url>0</url>\n</image>\n},
1553        "Image with undefined link does not render the Image - RSS version 0.9"
1554    );
1555}
1556
1557
1558{
1559    my $rss = create_rss_with_image_w_undef_link({version => "1.0"});
1560    # TEST
1561    contains ($rss,
1562        qq{<image rdf:about="0">\n<title>freshmeat.net</title>\n} .
1563        qq{<url>0</url>\n</image>\n},
1564        "Image with undefined link does not render the Image - RSS version 1.0"
1565    );
1566}
1567
1568{
1569    my $rss = create_channel_rss({
1570            version => "1.0",
1571            channel_params => [about => "http://xml-rss-hackers.tld/"],
1572        });
1573    # TEST
1574    contains($rss, "<channel rdf:about=\"http://xml-rss-hackers.tld/\">\n" .
1575        "<title>freshmeat.net</title>\n" .
1576        "<link>http://freshmeat.net</link>\n" .
1577        "<description>Linux software</description>\n" .
1578        "<items>\n",
1579        "1.0 - channel/about overrides the rdf:about attribute."
1580    );
1581}
1582
1583{
1584    my $rss = create_channel_rss({
1585        version => "1.0",
1586        channel_params =>
1587        [
1588            taxo => ["Foo", "Bar", "QuGof", "Lambda&Delta"],
1589        ],
1590    });
1591    # TEST
1592    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1593        "<title>freshmeat.net</title>\n" .
1594        "<link>http://freshmeat.net</link>\n" .
1595        "<description>Linux software</description>\n" .
1596        qq{<taxo:topics>\n  <rdf:Bag>\n} .
1597        qq{    <rdf:li resource="Foo" />\n} .
1598        qq{    <rdf:li resource="Bar" />\n} .
1599        qq{    <rdf:li resource="QuGof" />\n} .
1600        qq{    <rdf:li resource="Lambda&#x26;Delta" />\n} .
1601        qq{  </rdf:Bag>\n</taxo:topics>\n} .
1602        "<items>\n",
1603        "1.0 - taxo topics"
1604    );
1605}
1606
1607{
1608    my $rss = create_channel_rss({
1609        version => "1.0",
1610        channel_params =>
1611        [
1612            admin => { 'foobar' => "Quod", },
1613        ],
1614    });
1615    # TEST
1616    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1617        "<title>freshmeat.net</title>\n" .
1618        "<link>http://freshmeat.net</link>\n" .
1619        "<description>Linux software</description>\n" .
1620        "<admin:foobar>Quod</admin:foobar>\n" .
1621        "<items>\n",
1622        '1.0 - channel/[module] with unknown key'
1623    );
1624}
1625
1626{
1627    my $rss = create_channel_rss({
1628        version => "1.0",
1629        channel_params =>
1630        [
1631            eloq => { 'grow' => "There", },
1632        ],
1633    });
1634
1635    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1636    # TEST
1637    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
1638        "<title>freshmeat.net</title>\n" .
1639        "<link>http://freshmeat.net</link>\n" .
1640        "<description>Linux software</description>\n" .
1641        "<eloq:grow>There</eloq:grow>\n" .
1642        "<items>\n",
1643        '1.0 - channel/[module] with new module'
1644    );
1645}
1646
1647{
1648    my $rss = create_rss_1({
1649        version => "1.0",
1650        image_params =>
1651        [
1652            admin => { 'foobar' => "Quod", },
1653        ],
1654    });
1655    # TEST
1656    contains($rss, "<image rdf:about=\"0\">\n" .
1657        "<title>freshmeat.net</title>\n" .
1658        "<url>0</url>\n" .
1659        "<link>http://freshmeat.net/</link>\n" .
1660        "<admin:foobar>Quod</admin:foobar>\n" .
1661        "</image>",
1662        '1.0 - image/[module] with unknown key'
1663    );
1664}
1665
1666{
1667    my $rss = create_rss_1({
1668        version => "1.0",
1669        image_params =>
1670        [
1671            eloq => { 'grow' => "There", },
1672        ],
1673    });
1674
1675    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1676    # TEST
1677    contains($rss, "<image rdf:about=\"0\">\n" .
1678        "<title>freshmeat.net</title>\n" .
1679        "<url>0</url>\n" .
1680        "<link>http://freshmeat.net/</link>\n" .
1681        "<eloq:grow>There</eloq:grow>\n" .
1682        "</image>",
1683        '1.0 - image/[module] with new module'
1684    );
1685}
1686
1687{
1688    my $rss = create_rss_1({
1689        version => "1.0",
1690        image_params =>
1691        [
1692            admin => { 'generatorAgent' => "Spozilla 5.5", },
1693        ],
1694    });
1695    # TEST
1696    contains($rss, "<image rdf:about=\"0\">\n" .
1697        "<title>freshmeat.net</title>\n" .
1698        "<url>0</url>\n" .
1699        "<link>http://freshmeat.net/</link>\n" .
1700        "<admin:generatorAgent rdf:resource=\"Spozilla 5.5\" />\n" .
1701        "</image>",
1702        '1.0 - image/[module] with known module'
1703    );
1704}
1705
1706{
1707    my $rss = create_channel_rss({
1708        version => "1.0",
1709    });
1710
1711    $rss->add_item(
1712        title => "In the Jungle",
1713        link => "http://jungle.tld/Enter/",
1714        taxo => ["Foo","Loom", "<Ard>", "Yok&Dol"],
1715    );
1716
1717    # TEST
1718    contains($rss, "<item rdf:about=\"http://jungle.tld/Enter/\">\n" .
1719        "<title>In the Jungle</title>\n" .
1720        "<link>http://jungle.tld/Enter/</link>\n" .
1721        qq{<taxo:topics>\n} .
1722        qq{  <rdf:Bag>\n} .
1723        qq{    <rdf:li resource="Foo" />\n} .
1724        qq{    <rdf:li resource="Loom" />\n} .
1725        qq{    <rdf:li resource="&#x3C;Ard&#x3E;" />\n} .
1726        qq{    <rdf:li resource="Yok&#x26;Dol" />\n} .
1727        qq{  </rdf:Bag>\n} .
1728        qq{</taxo:topics>\n} .
1729        "</item>\n",
1730        "1.0 - item/taxo:topics (with escaping)"
1731    );
1732}
1733
1734## Test the RSS 1.0 items' ad-hoc modules support.
1735
1736{
1737    my $rss = create_item_rss({
1738        version => "1.0",
1739        item_params =>
1740        [
1741            admin => { 'foobar' => "Quod", },
1742        ],
1743    });
1744
1745    # TEST
1746    contains($rss, "<item rdf:about=\"http://fc-solve.berlios.de/\">\n" .
1747        "<title>Freecell Solver</title>\n" .
1748        "<link>http://fc-solve.berlios.de/</link>\n" .
1749        "<admin:foobar>Quod</admin:foobar>\n" .
1750        "</item>",
1751        '1.0 - item/[module] with unknown key'
1752    );
1753}
1754
1755{
1756    my $rss = create_item_rss({
1757        version => "1.0",
1758        item_params =>
1759        [
1760            eloq => { 'grow' => "There", },
1761        ],
1762    });
1763
1764    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1765
1766    # TEST
1767    contains($rss, "<item rdf:about=\"http://fc-solve.berlios.de/\">\n" .
1768        "<title>Freecell Solver</title>\n" .
1769        "<link>http://fc-solve.berlios.de/</link>\n" .
1770        "<eloq:grow>There</eloq:grow>\n" .
1771        "</item>",
1772        '1.0 - item/[module] with new module'
1773    );
1774}
1775
1776{
1777    my $rss = create_item_rss({
1778        version => "1.0",
1779        item_params =>
1780        [
1781            admin => { 'generatorAgent' => "Spozilla 5.5", },
1782        ],
1783    });
1784
1785    # TEST
1786    contains($rss, "<item rdf:about=\"http://fc-solve.berlios.de/\">\n" .
1787        "<title>Freecell Solver</title>\n" .
1788        "<link>http://fc-solve.berlios.de/</link>\n" .
1789        "<admin:generatorAgent rdf:resource=\"Spozilla 5.5\" />\n" .
1790        "</item>",
1791        '1.0 - item/[module] with known module'
1792    );
1793}
1794
1795{
1796    my $rss = create_textinput_with_0_rss({version => "1.0",
1797            textinput_params => [admin => { 'foobar' => "Quod", },],
1798        });
1799    # TEST
1800    contains(
1801        $rss,
1802        ("<textinput rdf:about=\"0\">\n" .
1803         join("", map {"<$_>0</$_>\n"} (qw(title description name link))) .
1804         "<admin:foobar>Quod</admin:foobar>\n" .
1805         "</textinput>\n"
1806        ),
1807        "1.0 - textinput/[module]",
1808    );
1809}
1810
1811{
1812    my $rss = create_channel_rss({
1813        version => "2.0",
1814        channel_params =>
1815        [
1816            admin => { 'generatorAgent' => "Spozilla 5.5", },
1817        ],
1818    });
1819
1820    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1821    # TEST
1822
1823    contains($rss, "<channel>\n" .
1824        "<title>freshmeat.net</title>\n" .
1825        "<link>http://freshmeat.net</link>\n" .
1826        "<description>Linux software</description>\n" .
1827        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1828        "<admin:generatorAgent rdf:resource=\"Spozilla 5.5\" />\n" .
1829        "\n" .
1830        "<item>\n",
1831        '2.0 - channel/[module] with known module and key'
1832    );
1833}
1834
1835
1836{
1837    my $rss = create_channel_rss({
1838        version => "2.0",
1839        channel_params =>
1840        [
1841            admin => { 'foobar' => "Quod", },
1842        ],
1843    });
1844    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1845    # TEST
1846    contains($rss, "<channel>\n" .
1847        "<title>freshmeat.net</title>\n" .
1848        "<link>http://freshmeat.net</link>\n" .
1849        "<description>Linux software</description>\n" .
1850        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1851        "<admin:foobar>Quod</admin:foobar>\n" .
1852        "\n" .
1853        "<item>\n",
1854        '2.0 - channel/[module] with unknown key'
1855    );
1856}
1857
1858{
1859    my $rss = create_channel_rss({
1860        version => "2.0",
1861        channel_params =>
1862        [
1863            eloq => { 'grow' => "There", },
1864        ],
1865    });
1866
1867    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1868    # TEST
1869    contains($rss, "<channel>\n" .
1870        "<title>freshmeat.net</title>\n" .
1871        "<link>http://freshmeat.net</link>\n" .
1872        "<description>Linux software</description>\n" .
1873        "<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate>\n" .
1874        "<eloq:grow>There</eloq:grow>\n" .
1875        "\n" .
1876        "<item>\n",
1877        '2.0 - channel/[module] with new module'
1878    );
1879}
1880
1881
1882## Testing the RSS 2.0 Image Modules Support
1883
1884{
1885    my $rss = create_rss_1({
1886        version => "2.0",
1887        image_params =>
1888        [
1889            admin => { 'foobar' => "Quod", },
1890        ],
1891    });
1892    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1893    # TEST
1894    contains($rss, "<image>\n" .
1895        "<title>freshmeat.net</title>\n" .
1896        "<url>0</url>\n" .
1897        "<link>http://freshmeat.net/</link>\n" .
1898        "<admin:foobar>Quod</admin:foobar>\n" .
1899        "</image>\n",
1900        '2.0 - image/[module] with unknown key'
1901    );
1902}
1903
1904{
1905    my $rss = create_rss_1({
1906        version => "2.0",
1907        image_params =>
1908        [
1909            eloq => { 'grow' => "There", },
1910        ],
1911    });
1912
1913    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1914    # TEST
1915    contains($rss, "<image>\n" .
1916        "<title>freshmeat.net</title>\n" .
1917        "<url>0</url>\n" .
1918        "<link>http://freshmeat.net/</link>\n" .
1919        "<eloq:grow>There</eloq:grow>\n" .
1920        "</image>",
1921        '2.0 - image/[module] with new module'
1922    );
1923}
1924
1925{
1926    my $rss = create_rss_1({
1927        version => "2.0",
1928        image_params =>
1929        [
1930            admin => { 'generatorAgent' => "Spozilla 5.5", },
1931        ],
1932    });
1933    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1934    # TEST
1935    contains($rss, "<image>\n" .
1936        "<title>freshmeat.net</title>\n" .
1937        "<url>0</url>\n" .
1938        "<link>http://freshmeat.net/</link>\n" .
1939        "<admin:generatorAgent rdf:resource=\"Spozilla 5.5\" />\n" .
1940        "</image>",
1941        '2.0 - image/[module] with known module'
1942    );
1943}
1944
1945## Test the RSS 2.0 items' ad-hoc modules support.
1946
1947{
1948    my $rss = create_item_rss({
1949        version => "2.0",
1950        item_params =>
1951        [
1952            admin => { 'foobar' => "Quod", },
1953        ],
1954    });
1955    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1956
1957    # TEST
1958    contains($rss, "<item>\n" .
1959        "<title>Freecell Solver</title>\n" .
1960        "<link>http://fc-solve.berlios.de/</link>\n" .
1961        "<admin:foobar>Quod</admin:foobar>\n" .
1962        "</item>",
1963        '2.0 - item/[module] with unknown key'
1964    );
1965}
1966
1967{
1968    my $rss = create_item_rss({
1969        version => "2.0",
1970        item_params =>
1971        [
1972            eloq => { 'grow' => "There", },
1973        ],
1974    });
1975
1976    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
1977
1978    # TEST
1979    contains($rss, "<item>\n" .
1980        "<title>Freecell Solver</title>\n" .
1981        "<link>http://fc-solve.berlios.de/</link>\n" .
1982        "<eloq:grow>There</eloq:grow>\n" .
1983        "</item>",
1984        '2.0 - item/[module] with new module'
1985    );
1986}
1987
1988{
1989    my $rss = create_item_rss({
1990        version => "2.0",
1991        item_params =>
1992        [
1993            admin => { 'generatorAgent' => "Spozilla 5.5", },
1994        ],
1995    });
1996    $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/");
1997
1998    # TEST
1999    contains($rss, "<item>\n" .
2000        "<title>Freecell Solver</title>\n" .
2001        "<link>http://fc-solve.berlios.de/</link>\n" .
2002        "<admin:generatorAgent rdf:resource=\"Spozilla 5.5\" />\n" .
2003        "</item>",
2004        '2.0 - item/[module] with known module'
2005    );
2006}
2007
2008## Test the RSS 2.0 skipping-items condition.
2009
2010{
2011    my $rss = create_rss_without_item({
2012        version => "2.0",
2013    });
2014    $rss->add_item(
2015        link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
2016    );
2017
2018    # TEST
2019    not_contains($rss, "<item>\n",
2020        '2.0 - Item without description or title is skipped'
2021    );
2022}
2023
2024## Test the RSS 2.0 <source url= condition.
2025{
2026    # TEST:$num_iters=3;
2027    foreach my $s (
2028        [undef, "http://www.hercules.tld/",],
2029        ["Hercules", undef,],
2030        [undef, undef],
2031        )
2032    {
2033        my $rss = create_item_with_0_rss({version => "2.0",
2034                item_params =>
2035                [
2036                    title => "Foo&Bar",
2037                    link => "http://www.mylongtldyeahbaby/",
2038                    source => $s->[0],
2039                    sourceUrl => $s->[1],
2040                ],
2041            }
2042        );
2043
2044        # TEST*$num_iters
2045        contains(
2046            $rss,
2047            ("<item>\n" .
2048             "<title>Foo&#x26;Bar</title>\n" .
2049             "<link>http://www.mylongtldyeahbaby/</link>\n" .
2050             "</item>"
2051             ),
2052            "2.0 - item - Source and/or Source URL are not defined",
2053        );
2054    }
2055}
2056
2057{
2058    # Here we create an RSS 2.0 object and render it as the output
2059    # version "3.5" in order to test that version 1.0 is the default
2060    # version for output.
2061    my $rss = create_channel_rss({
2062            version => "2.0",
2063            channel_params =>
2064            [copyright => "Martha", managingEditor => 0,],
2065            omit_date => 1,
2066        });
2067    $rss->{output} = "3.5";
2068    # TEST
2069    contains($rss, "<channel rdf:about=\"http://freshmeat.net\">\n" .
2070        "<title>freshmeat.net</title>\n" .
2071        "<link>http://freshmeat.net</link>\n" .
2072        "<description>Linux software</description>\n" .
2073        "<dc:rights>Martha</dc:rights>\n" .
2074        "<dc:publisher>0</dc:publisher>\n" .
2075        "<items>\n",
2076        "Unknown version renders as 1.0"
2077    );
2078}
2079
2080{
2081    my $version = "0.91";
2082    my $rss = create_rss_1({
2083            version => $version,
2084            image_link => "Hello <there&amp;Yes>",
2085            rss_args => ["encode_output" => 0],
2086        });
2087    # TEST
2088    contains($rss,
2089        "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n<link>Hello <there&amp;Yes></link>\n</image>\n",
2090        "Testing encode_output is false",
2091    );
2092}
2093
2094sub named_encode
2095{
2096    my ($self, $text) = @_;
2097
2098    if (!defined($text)) {
2099        require Carp;
2100        Carp::confess "\$text is undefined in XML::RSS::_encode(). We don't know how " . "to handle it!";
2101    }
2102
2103    my $encoded_text = '';
2104
2105    while ($text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s) {
2106        # we use &named; entities here because it's HTML
2107        $encoded_text .= encode_entities($1) . $2;
2108    }
2109
2110    # we use numeric entities here because it's XML
2111    $encoded_text .= encode_entities($text);
2112
2113    return $encoded_text;
2114}
2115
2116{
2117    my $version = "0.91";
2118    my $rss = create_rss_1({
2119            version => $version,
2120            image_link => "Hello <there&Yes>",
2121            rss_args => ["encode_cb" => \&named_encode],
2122        });
2123    # TEST
2124    contains($rss,
2125        "<image>\n<title>freshmeat.net</title>\n<url>0</url>\n<link>Hello &lt;there&amp;Yes&gt;</link>\n</image>\n",
2126        "Testing encode_cb with named encodings",
2127    );
2128}
2129
2130{
2131    my $rss = create_channel_rss({
2132            version => "0.91",
2133            image_link => undef,
2134            channel_params => [ title => "Hello and <![CDATA[Aloha<&>]]>"],
2135        });
2136
2137    # TEST
2138    contains($rss,
2139        "<title>Hello and <![CDATA[Aloha<&>]]></title>",
2140    );
2141}
2142
2143################
2144### RSS Parsing Tests:
2145### We generate RSS and test that we get the same results.
2146################
2147
2148sub parse_generated_rss
2149{
2150    my $args = shift;
2151
2152    my $gen_func = $args->{'func'};
2153
2154    my $rss_generator = $gen_func->($args);
2155
2156    $rss_generator->{output} = $args->{version};
2157
2158    my $output = $rss_generator->as_string();
2159
2160    if ($args->{postproc})
2161    {
2162        $args->{postproc}->(\$output);
2163    }
2164
2165    my $parser = XML::RSS->new(version => $args->{version});
2166
2167    $parser->parse($output);
2168
2169    return $parser;
2170}
2171
2172{
2173    my $rss =
2174        parse_generated_rss({
2175            func => \&create_textinput_with_0_rss,
2176            version => "0.9",
2177            textinput_params => [
2178                description => "Welcome to the Jungle.",
2179                'link' => "http://fooque.tld/",
2180                'title' => "The Jungle of the City",
2181                'name' => "There's more than one way to do it.",
2182                ],
2183            postproc => sub {
2184                    for (${shift()})
2185                    {
2186                        s{(<rdf:RDF)[^>]*(>)}{<rss version="0.9">};
2187                        s{</rdf:RDF>}{</rss>};
2188                    }
2189            },
2190        });
2191
2192    # TEST
2193    is ($rss->{textinput}->{description},
2194        "Welcome to the Jungle.",
2195        "0.9 parse - textinput/description",
2196    );
2197
2198    # TEST
2199    is ($rss->{textinput}->{link},
2200        "http://fooque.tld/",
2201        "0.9 parse - textinput/link",
2202    );
2203
2204    # TEST
2205    is ($rss->{textinput}->{title},
2206        "The Jungle of the City",
2207        "0.9 parse - textinput/title",
2208    );
2209
2210    # TEST
2211    is ($rss->{textinput}->{name},
2212        "There's more than one way to do it.",
2213        "0.9 parse - textinput/name",
2214    );
2215}
2216
2217{
2218    my $rss_parser =
2219        parse_generated_rss(
2220            {
2221                func => \&create_textinput_with_0_rss,
2222                version => "0.9",
2223                textinput_params => [
2224                    description => "Welcome to the Jungle.",
2225                    'link' => "http://fooque.tld/",
2226                    'title' => "The Jungle of the City",
2227                    'name' => "There's more than one way to do it.",
2228                ],
2229                postproc => sub {
2230                    for (${shift()})
2231                    {
2232                        s{(<rdf:RDF)[^>]*(>)}{<rss version="0.9">};
2233                        s{</rdf:RDF>}{</rss>};
2234                        s{<(/?)textinput>}{<$1textInput>}g;
2235                    }
2236                },
2237            }
2238        );
2239
2240    # TEST
2241    is ($rss_parser->{textinput}->{description},
2242        "Welcome to the Jungle.",
2243        "0.9 parse - textinput/description",
2244    );
2245
2246    # TEST
2247    is ($rss_parser->{textinput}->{link},
2248        "http://fooque.tld/",
2249        "Parse textInput (with capital I) - textinput/link",
2250    );
2251
2252    # TEST
2253    is ($rss_parser->{textinput}->{title},
2254        "The Jungle of the City",
2255        "Parse textInput (with capital I) - textinput/title",
2256    );
2257
2258    # TEST
2259    is ($rss_parser->{textinput}->{name},
2260        "There's more than one way to do it.",
2261        "Parse textInput (with capital I) - textinput/name",
2262    );
2263}
2264
2265{
2266    my $rss_parser =
2267        parse_generated_rss(
2268            {
2269                func => \&create_textinput_with_0_rss,
2270                version => "0.9",
2271                textinput_params => [
2272                    description => "Welcome to the Jungle.",
2273                    'link' => "http://fooque.tld/",
2274                    'title' => "The Jungle of the City",
2275                    'name' => "There's more than one way to do it.",
2276                ],
2277                postproc => sub {
2278                    for (${shift()})
2279                    {
2280                        s{<(/?)textinput>}{<$1textInput>}g
2281                    }
2282                },
2283            }
2284        );
2285
2286    # TEST
2287    is ($rss_parser->{textinput}->{description},
2288        "Welcome to the Jungle.",
2289        "0.9 parse - textinput/description",
2290    );
2291
2292    # TEST
2293    is ($rss_parser->{textinput}->{link},
2294        "http://fooque.tld/",
2295        "Parse textInput (with capital I) - textinput/link",
2296    );
2297
2298    # TEST
2299    is ($rss_parser->{textinput}->{title},
2300        "The Jungle of the City",
2301        "Parse textInput (with capital I) - textinput/title",
2302    );
2303
2304    # TEST
2305    is ($rss_parser->{textinput}->{name},
2306        "There's more than one way to do it.",
2307        "Parse textInput (with capital I) - textinput/name",
2308    )
2309}
2310
2311{
2312    my $rss_parser =
2313        parse_generated_rss(
2314            {
2315                func => \&create_skipHours_rss,
2316                version => "0.91",
2317                skipHours_params => [ hour => "5" ],
2318            }
2319        );
2320
2321    # TEST
2322    is ($rss_parser->{skipHours}->{hour},
2323        "5",
2324        "Parse 0.91 - skipHours/hour",
2325    );
2326}
2327
2328{
2329    my $rss_parser =
2330        parse_generated_rss(
2331            {
2332                func => \&create_skipHours_rss,
2333                version => "2.0",
2334                skipHours_params => [ hour => "5" ],
2335            }
2336        );
2337
2338    # TEST
2339    is ($rss_parser->{skipHours}->{hour},
2340        "5",
2341        "Parse 2.0 - skipHours/hour",
2342    );
2343}
2344
2345## Test the skipDays parsing.
2346
2347{
2348    my $rss_parser =
2349        parse_generated_rss(
2350            {
2351                func => \&create_skipDays_rss,
2352                version => "0.91",
2353                skipDays_params => [ day => "5" ],
2354            }
2355        );
2356
2357    # TEST
2358    is ($rss_parser->{skipDays}->{day},
2359        "5",
2360        "Parse 0.91 - skipDays/day",
2361    );
2362}
2363
2364{
2365    my $rss_parser =
2366        parse_generated_rss(
2367            {
2368                func => \&create_skipDays_rss,
2369                version => "2.0",
2370                skipDays_params => [ day => "5" ],
2371            }
2372        );
2373
2374    # TEST
2375    is ($rss_parser->{skipDays}->{day},
2376        "5",
2377        "Parse 2.0 - skipDays/day",
2378    );
2379}
2380
2381{
2382    my $rss_parser = XML::RSS->new(version => "2.0");
2383
2384    $rss_parser->parse(<<'EOF');
2385<?xml version="1.0" encoding="UTF-8"?>
2386
2387<rss version="2.0"
2388 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
2389 xmlns:foo="http://foo.tld/foobar/"
2390>
2391
2392<channel>
2393<title>Test 2.0 Feed</title>
2394<link>http://example.com/</link>
2395<description></description>
2396<language>en-us</language>
2397<copyright>Copyright 2002</copyright>
2398<pubDate>2007-01-19T14:21:43+0200</pubDate>
2399<lastBuildDate>2007-01-19T14:21:43+0200</lastBuildDate>
2400<docs>http://backend.userland.com/rss</docs>
2401<managingEditor>editor@example.com</managingEditor>
2402<webMaster>webmaster@example.com</webMaster>
2403<category>MyCategory</category>
2404<generator>XML::RSS Test</generator>
2405<ttl>60</ttl>
2406
2407<image>
2408<title>Test Image</title>
2409<url>http://example.com/example.gif</url>
2410<link>http://example.com/</link>
2411<height>25</height>
2412<description>Test Image</description>
2413<foo:hello>Hi there!</foo:hello>
2414</image>
2415
2416<item>
2417<title>This is an item</title>
2418<link>http://example.com/2007/01/19</link>
2419<description>Yadda yadda yadda - R&#x26;D;</description>
2420<author>joeuser@example.com</author>
2421<category>MyCategory</category>
2422<comments>http://example.com/2007/01/19/comments.html</comments>
2423<guid isPermaLink="true">http://example.com/2007/01/19</guid>
2424<pubDate>Fri 19 Jan 2007 02:21:43 PM IST GMT</pubDate>
2425<source url="http://example.com">my brain</source>
2426<enclosure url="http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent" type="application/x-bittorrent" />
2427</item>
2428
2429</channel>
2430</rss>
2431EOF
2432
2433    # TEST
2434    is ($rss_parser->{image}->{"http://foo.tld/foobar/"}->{hello},
2435        "Hi there!",
2436        "Parsing 2.0 - element in a different namespace contained in image",
2437    );
2438}
2439
2440{
2441    my $rss_parser = XML::RSS->new(version => "1.0");
2442
2443    $rss_parser->parse(<<'EOF');
2444<?xml version="1.0" encoding="UTF-8"?>
2445
2446<rdf:RDF
2447 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2448 xmlns="http://purl.org/rss/1.0/"
2449 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2450 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2451 xmlns:dc="http://purl.org/dc/elements/1.1/"
2452 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2453 xmlns:my="http://purl.org/my/rss/module/"
2454 xmlns:admin="http://webns.net/mvcb/"
2455>
2456
2457<channel rdf:about="http://example.com/">
2458<title>Test 1.0 Feed</title>
2459<link>http://example.com/</link>
2460<description>To lead by example</description>
2461<dc:date>2007-01-19T14:21:18+0200</dc:date>
2462<items>
2463 <rdf:Seq>
2464  <rdf:li rdf:resource="http://example.com/2007/01/19" />
2465 </rdf:Seq>
2466</items>
2467<image rdf:resource="http://example.com/example.gif" />
2468<textinput rdf:resource="http://example.com/search.pl" />
2469</channel>
2470
2471<image rdf:about="http://example.com/example.gif" xmlns="">
2472<title>Test Image</title>
2473<url>http://example.com/example.gif</url>
2474<link>http://example.com/</link>
2475<foo>Aye Karamba</foo>
2476</image>
2477
2478<item rdf:about="http://example.com/2007/01/19">
2479<title>This is an item</title>
2480<link>http://example.com/2007/01/19</link>
2481<description>Yadda &#x26; yadda &#x26; yadda</description>
2482<dc:creator>joeuser@example.com</dc:creator>
2483</item>
2484
2485<textinput rdf:about="http://example.com/search.pl">
2486<title>Search</title>
2487<description>Search for an example</description>
2488<name>q</name>
2489<link>http://example.com/search.pl</link>
2490</textinput>
2491
2492</rdf:RDF>
2493EOF
2494
2495    # TEST
2496    is ($rss_parser->{image}->{""}->{foo},
2497        "Aye Karamba",
2498        "Parsing 1.0 - element in a null namespace contained in image",
2499    );
2500}
2501
2502{
2503    my $rss_parser = XML::RSS->new(version => "2.0");
2504
2505    $rss_parser->parse(<<'EOF');
2506<?xml version="1.0" encoding="UTF-8"?>
2507
2508<rss version="2.0"
2509 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
2510 xmlns:foo="http://foo.tld/foobar/"
2511>
2512
2513<channel>
2514<title>Test 2.0 Feed</title>
2515<link>http://example.com/</link>
2516<description></description>
2517<language>en-us</language>
2518<copyright>Copyright 2002</copyright>
2519<pubDate>2007-01-19T14:21:43+0200</pubDate>
2520<lastBuildDate>2007-01-19T14:21:43+0200</lastBuildDate>
2521<docs>http://backend.userland.com/rss</docs>
2522<managingEditor>editor@example.com</managingEditor>
2523<webMaster>webmaster@example.com</webMaster>
2524<category>MyCategory</category>
2525<generator>XML::RSS Test</generator>
2526<ttl>60</ttl>
2527
2528<image>
2529<title>Test Image</title>
2530<url>http://example.com/example.gif</url>
2531<link>http://example.com/</link>
2532<height>25</height>
2533<description>Test Image</description>
2534</image>
2535
2536<item>
2537<title>This is an item</title>
2538<link>http://example.com/2007/01/19</link>
2539<description>Yadda yadda yadda - R&#x26;D;</description>
2540<author>joeuser@example.com</author>
2541<category>MyCategory</category>
2542<comments>http://example.com/2007/01/19/comments.html</comments>
2543<guid isPermaLink="true">http://example.com/2007/01/19</guid>
2544<pubDate>Fri 19 Jan 2007 02:21:43 PM IST GMT</pubDate>
2545<source url="http://example.com">my brain</source>
2546<enclosure url="http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent" type="application/x-bittorrent" />
2547<foo:hello>Hi there!</foo:hello>
2548</item>
2549
2550</channel>
2551</rss>
2552EOF
2553
2554    # TEST
2555    is ($rss_parser->{items}->[0]->{"http://foo.tld/foobar/"}->{hello},
2556        "Hi there!",
2557        "Parsing 2.0 - element in a different namespace contained in an item",
2558    );
2559}
2560
2561{
2562    my $rss_parser = XML::RSS->new(version => "1.0");
2563
2564    $rss_parser->parse(<<'EOF');
2565<?xml version="1.0" encoding="UTF-8"?>
2566
2567<rdf:RDF
2568 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2569 xmlns="http://purl.org/rss/1.0/"
2570 xmlns:alterrss="http://purl.org/rss/1.0/"
2571 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2572 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2573 xmlns:dc="http://purl.org/dc/elements/1.1/"
2574 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2575 xmlns:my="http://purl.org/my/rss/module/"
2576 xmlns:admin="http://webns.net/mvcb/"
2577>
2578
2579<channel rdf:about="http://example.com/">
2580<title>Test 1.0 Feed</title>
2581<link>http://example.com/</link>
2582<description>To lead by example</description>
2583<dc:date>2007-01-19T14:21:18+0200</dc:date>
2584<items>
2585 <rdf:Seq>
2586  <rdf:li rdf:resource="http://example.com/2007/01/19" />
2587 </rdf:Seq>
2588</items>
2589<image rdf:resource="http://example.com/example.gif" />
2590<textinput rdf:resource="http://example.com/search.pl" />
2591</channel>
2592
2593<image rdf:about="http://example.com/example.gif">
2594<title>Test Image</title>
2595<url>http://example.com/example.gif</url>
2596<link>http://example.com/</link>
2597</image>
2598
2599<alterrss:item rdf:about="http://example.com/2007/01/19" xmlns="">
2600<title>This is an item</title>
2601<link>http://example.com/2007/01/19</link>
2602<description>Yadda &#x26; yadda &#x26; yadda</description>
2603<dc:creator>joeuser@example.com</dc:creator>
2604<foo>Aye Karamba</foo>
2605</alterrss:item>
2606
2607<textinput rdf:about="http://example.com/search.pl">
2608<title>Search</title>
2609<description>Search for an example</description>
2610<name>q</name>
2611<link>http://example.com/search.pl</link>
2612</textinput>
2613
2614</rdf:RDF>
2615EOF
2616
2617    # TEST
2618    is ($rss_parser->{items}->[0]->{""}->{foo},
2619        "Aye Karamba",
2620        "Parsing 1.0 - element in a null namespace contained in image",
2621    );
2622}
2623
2624{
2625    my $rss_parser = XML::RSS->new(version => "2.0");
2626
2627    $rss_parser->parse(<<'EOF');
2628<?xml version="1.0" encoding="UTF-8"?>
2629
2630<rss version="2.0"
2631 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
2632 xmlns:foo="http://foo.tld/foobar/"
2633>
2634
2635<channel>
2636<title>Test 2.0 Feed</title>
2637<link>http://example.com/</link>
2638<description></description>
2639<language>en-us</language>
2640<copyright>Copyright 2002</copyright>
2641<pubDate>2007-01-19T14:21:43+0200</pubDate>
2642<lastBuildDate>2007-01-19T14:21:43+0200</lastBuildDate>
2643<docs>http://backend.userland.com/rss</docs>
2644<managingEditor>editor@example.com</managingEditor>
2645<webMaster>webmaster@example.com</webMaster>
2646<category>MyCategory</category>
2647<generator>XML::RSS Test</generator>
2648<ttl>60</ttl>
2649
2650<image>
2651<title>Test Image</title>
2652<url>http://example.com/example.gif</url>
2653<link>http://example.com/</link>
2654<height>25</height>
2655<description>Test Image</description>
2656</image>
2657
2658<item>
2659<title>This is an item</title>
2660<link>http://example.com/2007/01/19</link>
2661<description>Yadda yadda yadda - R&#x26;D;</description>
2662<author>joeuser@example.com</author>
2663<category>MyCategory</category>
2664<comments>http://example.com/2007/01/19/comments.html</comments>
2665<guid isPermaLink="true">http://example.com/2007/01/19</guid>
2666<pubDate>Fri 19 Jan 2007 02:21:43 PM IST GMT</pubDate>
2667<source url="http://example.com">my brain</source>
2668<enclosure url="http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent" type="application/x-bittorrent" />
2669</item>
2670
2671<textInput>
2672<title>Search</title>
2673<description>Search for an example</description>
2674<name>q</name>
2675<link>http://example.com/search.pl</link>
2676<foo:hello>Show Baloon</foo:hello>
2677</textInput>
2678
2679</channel>
2680</rss>
2681EOF
2682
2683    # TEST
2684    is ($rss_parser->{textinput}->{"http://foo.tld/foobar/"}->{hello},
2685        "Show Baloon",
2686        "Parsing 2.0 - element in a different namespace contained in a textinput",
2687    );
2688}
2689
2690{
2691    my $rss_parser = XML::RSS->new(version => "1.0");
2692
2693    $rss_parser->parse(<<'EOF');
2694<?xml version="1.0" encoding="UTF-8"?>
2695
2696<rdf:RDF
2697 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2698 xmlns="http://purl.org/rss/1.0/"
2699 xmlns:alterrss="http://purl.org/rss/1.0/"
2700 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2701 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2702 xmlns:dc="http://purl.org/dc/elements/1.1/"
2703 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2704 xmlns:my="http://purl.org/my/rss/module/"
2705 xmlns:admin="http://webns.net/mvcb/"
2706>
2707
2708<channel rdf:about="http://example.com/">
2709<title>Test 1.0 Feed</title>
2710<link>http://example.com/</link>
2711<description>To lead by example</description>
2712<dc:date>2007-01-19T14:21:18+0200</dc:date>
2713<items>
2714 <rdf:Seq>
2715  <rdf:li rdf:resource="http://example.com/2007/01/19" />
2716 </rdf:Seq>
2717</items>
2718<image rdf:resource="http://example.com/example.gif" />
2719<textinput rdf:resource="http://example.com/search.pl" />
2720</channel>
2721
2722<image rdf:about="http://example.com/example.gif">
2723<title>Test Image</title>
2724<url>http://example.com/example.gif</url>
2725<link>http://example.com/</link>
2726</image>
2727
2728<item rdf:about="http://example.com/2007/01/19">
2729<title>This is an item</title>
2730<link>http://example.com/2007/01/19</link>
2731<description>Yadda &#x26; yadda &#x26; yadda</description>
2732<dc:creator>joeuser@example.com</dc:creator>
2733</item>
2734
2735<textinput rdf:about="http://example.com/search.pl" xmlns="">
2736<title>Search</title>
2737<description>Search for an example</description>
2738<name>q</name>
2739<link>http://example.com/search.pl</link>
2740<foo>Priceless</foo>
2741</textinput>
2742
2743</rdf:RDF>
2744EOF
2745
2746    # TEST
2747    is ($rss_parser->{textinput}->{""}->{foo},
2748        "Priceless",
2749        "Parsing 1.0 - element in a null namespace contained in a textinput",
2750    );
2751}
2752
2753{
2754    my $rss_parser = XML::RSS->new(version => "2.0");
2755
2756    $rss_parser->parse(<<'EOF');
2757<?xml version="1.0" encoding="UTF-8"?>
2758
2759<rss version="2.0"
2760 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
2761 xmlns:foo="http://foo.tld/foobar/"
2762>
2763
2764<channel>
2765<title>Test 2.0 Feed</title>
2766<link>http://example.com/</link>
2767<description></description>
2768<language>en-us</language>
2769<copyright>Copyright 2002</copyright>
2770<pubDate>2007-01-19T14:21:43+0200</pubDate>
2771<lastBuildDate>2007-01-19T14:21:43+0200</lastBuildDate>
2772<docs>http://backend.userland.com/rss</docs>
2773<managingEditor>editor@example.com</managingEditor>
2774<webMaster>webmaster@example.com</webMaster>
2775<category>MyCategory</category>
2776<generator>XML::RSS Test</generator>
2777<ttl>60</ttl>
2778<foo:hello>The RSS Must Flow</foo:hello>
2779
2780<image>
2781<title>Test Image</title>
2782<url>http://example.com/example.gif</url>
2783<link>http://example.com/</link>
2784<height>25</height>
2785<description>Test Image</description>
2786</image>
2787
2788<item>
2789<title>This is an item</title>
2790<link>http://example.com/2007/01/19</link>
2791<description>Yadda yadda yadda - R&#x26;D;</description>
2792<author>joeuser@example.com</author>
2793<category>MyCategory</category>
2794<comments>http://example.com/2007/01/19/comments.html</comments>
2795<guid isPermaLink="true">http://example.com/2007/01/19</guid>
2796<pubDate>Fri 19 Jan 2007 02:21:43 PM IST GMT</pubDate>
2797<source url="http://example.com">my brain</source>
2798<enclosure url="http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent" type="application/x-bittorrent" />
2799</item>
2800
2801<textInput>
2802<title>Search</title>
2803<description>Search for an example</description>
2804<name>q</name>
2805<link>http://example.com/search.pl</link>
2806</textInput>
2807
2808</channel>
2809</rss>
2810EOF
2811
2812    # TEST
2813    is ($rss_parser->{channel}->{"http://foo.tld/foobar/"}->{hello},
2814        "The RSS Must Flow",
2815        "Parsing 2.0 - element in a different namespace contained in a channel",
2816    );
2817}
2818
2819{
2820    my $rss_parser = XML::RSS->new(version => "1.0");
2821
2822    $rss_parser->parse(<<'EOF');
2823<?xml version="1.0" encoding="UTF-8"?>
2824
2825<rdf:RDF
2826 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2827 xmlns="http://purl.org/rss/1.0/"
2828 xmlns:alterrss="http://purl.org/rss/1.0/"
2829 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2830 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2831 xmlns:dc="http://purl.org/dc/elements/1.1/"
2832 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2833 xmlns:my="http://purl.org/my/rss/module/"
2834 xmlns:admin="http://webns.net/mvcb/"
2835>
2836
2837<channel rdf:about="http://example.com/" xmlns="">
2838<title>Test 1.0 Feed</title>
2839<link>http://example.com/</link>
2840<description>To lead by example</description>
2841<dc:date>2007-01-19T14:21:18+0200</dc:date>
2842<items>
2843 <rdf:Seq>
2844  <rdf:li rdf:resource="http://example.com/2007/01/19" />
2845 </rdf:Seq>
2846</items>
2847<image rdf:resource="http://example.com/example.gif" />
2848<textinput rdf:resource="http://example.com/search.pl" />
2849<foo>Placebo is here</foo>
2850</channel>
2851
2852<image rdf:about="http://example.com/example.gif">
2853<title>Test Image</title>
2854<url>http://example.com/example.gif</url>
2855<link>http://example.com/</link>
2856</image>
2857
2858<item rdf:about="http://example.com/2007/01/19">
2859<title>This is an item</title>
2860<link>http://example.com/2007/01/19</link>
2861<description>Yadda &#x26; yadda &#x26; yadda</description>
2862<dc:creator>joeuser@example.com</dc:creator>
2863</item>
2864
2865<textinput rdf:about="http://example.com/search.pl">
2866<title>Search</title>
2867<description>Search for an example</description>
2868<name>q</name>
2869<link>http://example.com/search.pl</link>
2870</textinput>
2871
2872</rdf:RDF>
2873EOF
2874
2875    # TEST
2876    is ($rss_parser->{channel}->{""}->{foo},
2877        "Placebo is here",
2878        "Parsing 1.0 - element in a null namespace contained in a channel",
2879    );
2880}
2881
2882{
2883    my $rss_parser = XML::RSS->new(version => "1.0");
2884
2885    $rss_parser->parse(<<'EOF');
2886<?xml version="1.0" encoding="UTF-8"?>
2887
2888<rdf:RDF
2889 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2890 xmlns="http://purl.org/rss/1.0/"
2891 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2892 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2893 xmlns:dc="http://purl.org/dc/elements/1.1/"
2894 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2895 xmlns:admin="http://webns.net/mvcb/"
2896>
2897
2898<channel rdf:about="http://freshmeat.net">
2899<title>freshmeat.net</title>
2900<link>http://freshmeat.net</link>
2901<description>Linux software</description>
2902<items>
2903 <rdf:Seq>
2904  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
2905  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
2906 </rdf:Seq>
2907</items>
2908</channel>
2909
2910<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
2911<title>GTKeyboard 0.85</title>
2912<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
2913</item>
2914
2915<item rdf:about="http://jungle.tld/Enter/">
2916<title>In the Jungle</title>
2917<link>http://jungle.tld/Enter/</link>
2918<taxo:topics>
2919  <rdf:Bag>
2920    <rdf:li resource="Foo" />
2921    <rdf:li resource="Loom" />
2922    <rdf:li resource="Hello" />
2923    <rdf:li resource="myowA" />
2924  </rdf:Bag>
2925</taxo:topics>
2926</item>
2927
2928</rdf:RDF>
2929EOF
2930
2931    # TEST
2932    is_deeply ($rss_parser->{items}->[1]->{taxo},
2933        ["Foo", "Loom", "Hello", "myowA"],
2934        "Parsing 1.0 - taxo items",
2935    );
2936}
2937
2938{
2939    my $rss_parser = XML::RSS->new(version => "1.0");
2940
2941    $rss_parser->parse(<<'EOF');
2942<?xml version="1.0" encoding="UTF-8"?>
2943
2944<rdf:RDF
2945 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2946 xmlns="http://purl.org/rss/1.0/"
2947 xmlns:content="http://purl.org/rss/1.0/modules/content/"
2948 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
2949 xmlns:dc="http://purl.org/dc/elements/1.1/"
2950 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
2951 xmlns:admin="http://webns.net/mvcb/"
2952>
2953
2954<channel rdf:about="http://freshmeat.net">
2955<title>freshmeat.net</title>
2956<link>http://freshmeat.net</link>
2957<description>Linux software</description>
2958<items>
2959 <rdf:Seq>
2960  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
2961  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
2962 </rdf:Seq>
2963</items>
2964</channel>
2965
2966<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
2967<title>GTKeyboard 0.85</title>
2968<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
2969</item>
2970
2971<item rdf:about="http://jungle.tld/Enter/">
2972<title>In the Jungle</title>
2973<link>http://jungle.tld/Enter/</link>
2974<taxo:topics>
2975  <rdf:Bag>
2976    <rdf:li resource="Everybody" />
2977    <rdf:li resource="needs" />
2978    <dc:hello />
2979    <rdf:li resource="a" />
2980    <rdf:li resource="[[[HUG]]]" />
2981  </rdf:Bag>
2982</taxo:topics>
2983</item>
2984
2985</rdf:RDF>
2986EOF
2987
2988    # TEST
2989    is_deeply ($rss_parser->{items}->[1]->{taxo},
2990        ["Everybody", "needs", "a", "[[[HUG]]]"],
2991        "Parsing 1.0 - taxo bag in <item> with junk elements",
2992    );
2993}
2994
2995{
2996    my $rss_parser = XML::RSS->new(version => "1.0");
2997
2998    $rss_parser->parse(<<'EOF');
2999<?xml version="1.0" encoding="UTF-8"?>
3000
3001<rdf:RDF
3002 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3003 xmlns="http://purl.org/rss/1.0/"
3004 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3005 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3006 xmlns:dc="http://purl.org/dc/elements/1.1/"
3007 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3008 xmlns:admin="http://webns.net/mvcb/"
3009>
3010
3011<channel rdf:about="http://freshmeat.net">
3012<title>freshmeat.net</title>
3013<link>http://freshmeat.net</link>
3014<description>Linux software</description>
3015<items>
3016 <rdf:Seq>
3017  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3018  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3019 </rdf:Seq>
3020</items>
3021<taxo:topics>
3022  <rdf:Bag>
3023    <rdf:li resource="Elastic" />
3024    <rdf:li resource="Plastic" />
3025    <rdf:li resource="stochastic" />
3026    <rdf:li resource="dynamic^^K" />
3027  </rdf:Bag>
3028</taxo:topics>
3029</channel>
3030
3031<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3032<title>GTKeyboard 0.85</title>
3033<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3034</item>
3035
3036<item rdf:about="http://jungle.tld/Enter/">
3037<title>In the Jungle</title>
3038<link>http://jungle.tld/Enter/</link>
3039<taxo:topics>
3040  <rdf:Bag>
3041    <rdf:li resource="Foo" />
3042    <rdf:li resource="Loom" />
3043    <rdf:li resource="Hello" />
3044    <rdf:li resource="myowA" />
3045  </rdf:Bag>
3046</taxo:topics>
3047</item>
3048
3049</rdf:RDF>
3050EOF
3051
3052    # TEST
3053    is_deeply ($rss_parser->{channel}->{taxo},
3054        ["Elastic", "Plastic", "stochastic", "dynamic^^K"],
3055        "Parsing 1.0 - taxo items in channel",
3056    );
3057}
3058
3059{
3060    my $rss_parser = XML::RSS->new(version => "1.0");
3061
3062    $rss_parser->parse(<<'EOF');
3063<?xml version="1.0" encoding="UTF-8"?>
3064
3065<rdf:RDF
3066 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3067 xmlns="http://purl.org/rss/1.0/"
3068 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3069 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3070 xmlns:dc="http://purl.org/dc/elements/1.1/"
3071 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3072 xmlns:admin="http://webns.net/mvcb/"
3073>
3074
3075<channel rdf:about="http://freshmeat.net">
3076<title>freshmeat.net</title>
3077<link>http://freshmeat.net</link>
3078<description>Linux software</description>
3079<items>
3080 <rdf:Seq>
3081  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3082  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3083 </rdf:Seq>
3084</items>
3085<taxo:topics>
3086  <rdf:Bag>
3087    <rdf:li resource="Elastic" />
3088    <rdf:li resource="Plastic" />
3089    <rdf:li resource="stochastic" />
3090    <dc:hello />
3091    <rdf:li resource="dynamic^^K" />
3092  </rdf:Bag>
3093</taxo:topics>
3094</channel>
3095
3096<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3097<title>GTKeyboard 0.85</title>
3098<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3099</item>
3100
3101<item rdf:about="http://jungle.tld/Enter/">
3102<title>In the Jungle</title>
3103<link>http://jungle.tld/Enter/</link>
3104<taxo:topics>
3105  <rdf:Bag>
3106    <rdf:li resource="Foo" />
3107    <rdf:li resource="Loom" />
3108    <rdf:li resource="Hello" />
3109    <rdf:li resource="myowA" />
3110  </rdf:Bag>
3111</taxo:topics>
3112</item>
3113
3114</rdf:RDF>
3115EOF
3116
3117    # TEST
3118    is_deeply ($rss_parser->{channel}->{taxo},
3119        ["Elastic", "Plastic", "stochastic", "dynamic^^K"],
3120        "Parsing 1.0 - taxo items in channel with junk items",
3121    );
3122}
3123
3124{
3125    my $rss_parser = XML::RSS->new(version => "1.0");
3126
3127    $rss_parser->parse(<<'EOF');
3128<?xml version="1.0" encoding="UTF-8"?>
3129
3130<rdf:RDF
3131 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3132 xmlns="http://purl.org/rss/1.0/"
3133 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3134 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3135 xmlns:dc="http://purl.org/dc/elements/1.1/"
3136 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3137 xmlns:admin="http://webns.net/mvcb/"
3138>
3139
3140<channel rdf:about="http://freshmeat.net">
3141<title>freshmeat.net</title>
3142<link>http://freshmeat.net</link>
3143<description>Linux software</description>
3144<items>
3145 <rdf:Seq>
3146  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3147  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3148 </rdf:Seq>
3149</items>
3150<taxo:topics>
3151  <rdf:Bag>
3152    <rdf:li resource="Elastic" />
3153    <rdf:li resource="Plastic" />
3154    <rdf:li resource="stochastic" />
3155    <dc:hello />
3156    <rdf:li resource="dynamic^^K" />
3157  </rdf:Bag>
3158</taxo:topics>
3159</channel>
3160
3161<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3162<title>GTKeyboard 0.85</title>
3163<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3164</item>
3165
3166<item rdf:about="http://jungle.tld/Enter/">
3167<title>In the Jungle</title>
3168<link>http://jungle.tld/Enter/</link>
3169<admin:hello>Gow</admin:hello>
3170</item>
3171
3172</rdf:RDF>
3173EOF
3174
3175    # TEST
3176    is ($rss_parser->{items}->[1]->{"http://webns.net/mvcb/"}->{hello},
3177        "Gow",
3178        "Parsing 1.0 - Elements inside <item> that don't exist in \%rdf_resource_fields",
3179    );
3180}
3181
3182{
3183    my $rss_parser = XML::RSS->new(version => "1.0");
3184
3185    $rss_parser->parse(<<'EOF');
3186<?xml version="1.0" encoding="UTF-8"?>
3187
3188<rdf:RDF
3189 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3190 xmlns="http://purl.org/rss/1.0/"
3191 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3192 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3193 xmlns:dc="http://purl.org/dc/elements/1.1/"
3194 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3195 xmlns:admin="http://webns.net/mvcb/"
3196>
3197
3198<channel rdf:about="http://freshmeat.net">
3199<title>freshmeat.net</title>
3200<link>http://freshmeat.net</link>
3201<description>Linux software</description>
3202<items>
3203 <rdf:Seq>
3204  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3205  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3206 </rdf:Seq>
3207</items>
3208<taxo:topics>
3209  <rdf:Bag>
3210    <rdf:li resource="Elastic" />
3211    <rdf:li resource="Plastic" />
3212    <rdf:li resource="stochastic" />
3213    <dc:hello />
3214    <rdf:li resource="dynamic^^K" />
3215  </rdf:Bag>
3216</taxo:topics>
3217</channel>
3218
3219<admin:generatorAgent>Gow</admin:generatorAgent>
3220<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3221<title>GTKeyboard 0.85</title>
3222<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3223</item>
3224
3225<item rdf:about="http://jungle.tld/Enter/">
3226<title>In the Jungle</title>
3227<link>http://jungle.tld/Enter/</link>
3228</item>
3229
3230</rdf:RDF>
3231EOF
3232
3233    # TEST
3234    ok ((!grep { exists($_->{"http://webns.net/mvcb/"}->{generatorAgent}) }
3235        @{$rss_parser->{items}}),
3236        "Parsing 1.0 - Elements that exist in \%rdf_resource_fields but not inside item",
3237    );
3238}
3239
3240{
3241    my $rss_parser = XML::RSS->new(version => "1.0");
3242
3243    $rss_parser->parse(<<'EOF');
3244<?xml version="1.0" encoding="UTF-8"?>
3245
3246<rdf:RDF
3247 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3248 xmlns="http://purl.org/rss/1.0/"
3249 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3250 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3251 xmlns:dc="http://purl.org/dc/elements/1.1/"
3252 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3253 xmlns:admin="http://webns.net/mvcb/"
3254>
3255
3256<channel rdf:about="http://freshmeat.net">
3257<title>freshmeat.net</title>
3258<link>http://freshmeat.net</link>
3259<description>Linux software</description>
3260<items>
3261 <rdf:Seq>
3262  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3263  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3264 </rdf:Seq>
3265</items>
3266<taxo:topics>
3267  <rdf:Bag>
3268    <rdf:li resource="Elastic" />
3269    <rdf:li resource="Plastic" />
3270    <rdf:li resource="stochastic" />
3271    <dc:hello />
3272    <rdf:li resource="dynamic^^K" />
3273  </rdf:Bag>
3274</taxo:topics>
3275</channel>
3276
3277<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3278<title>GTKeyboard 0.85</title>
3279<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3280</item>
3281
3282<item rdf:about="http://jungle.tld/Enter/">
3283<title>In the Jungle</title>
3284<link>http://jungle.tld/Enter/</link>
3285</item>
3286<enclosure foo="bar" good="them" />
3287
3288</rdf:RDF>
3289EOF
3290
3291    # TEST
3292    ok ((!grep { exists($_->{enclosure}) }
3293        @{$rss_parser->{items}}),
3294        "Parsing 1.0 - Testing \%empty_ok_elements",
3295    );
3296}
3297
3298{
3299    my $rss_parser = XML::RSS->new(version => "1.0");
3300
3301    $rss_parser->parse(<<'EOF');
3302<?xml version="1.0" encoding="UTF-8"?>
3303
3304<rdf:RDF
3305 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3306 xmlns="http://purl.org/rss/1.0/"
3307 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3308 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3309 xmlns:dc="http://purl.org/dc/elements/1.1/"
3310 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3311 xmlns:admin="http://webns.net/mvcb/"
3312 xmlns:foo="http://foobar.tld/foobardom/"
3313>
3314
3315<channel rdf:about="http://freshmeat.net">
3316<title>freshmeat.net</title>
3317<link>http://freshmeat.net</link>
3318<description>Linux software</description>
3319<items>
3320 <rdf:Seq>
3321  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3322  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3323 </rdf:Seq>
3324</items>
3325<taxo:topics>
3326  <rdf:Bag>
3327    <rdf:li resource="Elastic" />
3328    <rdf:li resource="Plastic" />
3329    <rdf:li resource="stochastic" />
3330    <rdf:li resource="dynamic^^K" />
3331  </rdf:Bag>
3332</taxo:topics>
3333</channel>
3334
3335<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3336<title>GTKeyboard 0.85</title>
3337<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3338</item>
3339
3340<foo:item rdf:about="http://jungle.tld/Enter/">
3341<title>In the Jungle</title>
3342<link>http://jungle.tld/Enter/</link>
3343</foo:item>
3344
3345</rdf:RDF>
3346EOF
3347
3348    # TEST
3349    is (scalar(@{$rss_parser->{items}}), 1, "Parse 1.0 with item in a different NS - There is 1 item");
3350
3351    # TEST
3352    is ($rss_parser->{items}->[0]->{title}, "GTKeyboard 0.85", "Parse 1.0 with item in a different NS - it is not the item in the other NS");
3353}
3354
3355{
3356    my $rss_parser = XML::RSS->new(version => "1.0");
3357
3358    $rss_parser->parse(<<'EOF');
3359<?xml version="1.0" encoding="UTF-8"?>
3360
3361<rdf:RDF
3362 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3363 xmlns="http://purl.org/rss/1.0/"
3364 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3365 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3366 xmlns:dc="http://purl.org/dc/elements/1.1/"
3367 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3368 xmlns:admin="http://webns.net/mvcb/"
3369 xmlns:foo="http://foobar.tld/foobardom/"
3370>
3371
3372<channel rdf:about="http://freshmeat.net">
3373<title>freshmeat.net</title>
3374<link>http://freshmeat.net</link>
3375<description>Linux software</description>
3376<items>
3377 <rdf:Seq>
3378  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3379  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3380 </rdf:Seq>
3381</items>
3382<taxo:topics>
3383  <rdf:Bag>
3384    <rdf:li resource="Elastic" />
3385    <rdf:li resource="Plastic" />
3386    <rdf:li resource="stochastic" />
3387    <rdf:li resource="dynamic^^K" />
3388  </rdf:Bag>
3389</taxo:topics>
3390</channel>
3391
3392<item xmlns="">
3393<title>In the Jungle</title>
3394<link>http://jungle.tld/Enter/</link>
3395</item>
3396
3397</rdf:RDF>
3398EOF
3399
3400    # TEST
3401    is (scalar(@{$rss_parser->{items}}), 0, "Parse 1.0 with item in null namespace");
3402}
3403
3404{
3405    my $rss_parser = XML::RSS->new(version => "1.0");
3406
3407    $rss_parser->parse(<<'EOF');
3408<?xml version="1.0" encoding="UTF-8"?>
3409
3410<rdf:RDF
3411 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3412 xmlns="http://purl.org/rss/1.0/"
3413 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3414 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3415 xmlns:dc="http://purl.org/dc/elements/1.1/"
3416 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3417 xmlns:my="http://purl.org/my/rss/module/"
3418 xmlns:admin="http://webns.net/mvcb/"
3419>
3420
3421<channel rdf:about="http://example.com/">
3422<title>Test 1.0 Feed</title>
3423<link>http://example.com/</link>
3424<description>To lead by example</description>
3425<dc:date>2007-01-19T14:21:18+0200</dc:date>
3426<items>
3427 <rdf:Seq>
3428  <rdf:li rdf:resource="http://example.com/2007/01/19" />
3429 </rdf:Seq>
3430</items>
3431<image rdf:resource="http://example.com/example.gif" />
3432<textinput rdf:resource="http://example.com/search.pl" />
3433</channel>
3434
3435<image rdf:about="http://example.com/example.gif" xmlns="">
3436<title>Test Image</title>
3437<url>http://example.com/example.gif</url>
3438<link>http://example.com/</link>
3439<dc:date>5 Sep 2006</dc:date>
3440</image>
3441
3442<item rdf:about="http://example.com/2007/01/19">
3443<title>This is an item</title>
3444<link>http://example.com/2007/01/19</link>
3445<description>Yadda &#x26; yadda &#x26; yadda</description>
3446<dc:creator>joeuser@example.com</dc:creator>
3447</item>
3448
3449<textinput rdf:about="http://example.com/search.pl">
3450<title>Search</title>
3451<description>Search for an example</description>
3452<name>q</name>
3453<link>http://example.com/search.pl</link>
3454</textinput>
3455
3456</rdf:RDF>
3457EOF
3458
3459    # TEST
3460    is ($rss_parser->{image}->{dc}->{date},
3461        "5 Sep 2006",
3462        "Parsing 1.0 - Known module in image",
3463    );
3464}
3465
3466{
3467    my $rss_parser = XML::RSS->new(version => "1.0");
3468
3469    $rss_parser->parse(<<'EOF');
3470<?xml version="1.0" encoding="UTF-8"?>
3471
3472<rdf:RDF
3473 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3474 xmlns="http://purl.org/rss/1.0/"
3475 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3476 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3477 xmlns:dc="http://purl.org/dc/elements/1.1/"
3478 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3479 xmlns:my="http://purl.org/my/rss/module/"
3480 xmlns:admin="http://webns.net/mvcb/"
3481>
3482
3483<channel rdf:about="http://example.com/">
3484<title>Test 1.0 Feed</title>
3485<link>http://example.com/</link>
3486<description>To lead by example</description>
3487<dc:date>2007-01-19T14:21:18+0200</dc:date>
3488<items>
3489 <rdf:Seq>
3490  <rdf:li rdf:resource="http://example.com/2007/01/19" />
3491 </rdf:Seq>
3492</items>
3493<image rdf:resource="http://example.com/example.gif" />
3494<textinput rdf:resource="http://example.com/search.pl" />
3495</channel>
3496
3497<image rdf:about="http://example.com/example.gif" xmlns="">
3498<title>Test Image</title>
3499<url>http://example.com/example.gif</url>
3500<link>http://example.com/</link>
3501</image>
3502
3503<item rdf:about="http://example.com/2007/01/19">
3504<title>This is an item</title>
3505<link>http://example.com/2007/01/19</link>
3506<description>Yadda &#x26; yadda &#x26; yadda</description>
3507<dc:creator>joeuser@example.com</dc:creator>
3508</item>
3509
3510<textinput rdf:about="http://example.com/search.pl">
3511<title>Search</title>
3512<description>Search for an example</description>
3513<name>q</name>
3514<link>http://example.com/search.pl</link>
3515<dc:date>5 May 1977</dc:date>
3516</textinput>
3517
3518</rdf:RDF>
3519EOF
3520
3521    # TEST
3522    is ($rss_parser->{textinput}->{dc}->{date},
3523        "5 May 1977",
3524        "Parsing 1.0 - Known module in a textinput",
3525    );
3526}
3527
3528{
3529    my $rss_parser = XML::RSS->new(version => "2.0");
3530
3531my $xml_text = <<'EOF';
3532<?xml version="1.0" encoding="UTF-8"?>
3533
3534<rss
3535 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
3536 xmlns:foo="http://foo.tld/foobar/"
3537>
3538
3539<channel>
3540<title>Test 2.0 Feed</title>
3541<link>http://example.com/</link>
3542<description></description>
3543<language>en-us</language>
3544<copyright>Copyright 2002</copyright>
3545<pubDate>2007-01-19T14:21:43+0200</pubDate>
3546<lastBuildDate>2007-01-19T14:21:43+0200</lastBuildDate>
3547<docs>http://backend.userland.com/rss</docs>
3548<managingEditor>editor@example.com</managingEditor>
3549<webMaster>webmaster@example.com</webMaster>
3550<category>MyCategory</category>
3551<generator>XML::RSS Test</generator>
3552<ttl>60</ttl>
3553
3554<image>
3555<title>Test Image</title>
3556<url>http://example.com/example.gif</url>
3557<link>http://example.com/</link>
3558<height>25</height>
3559<description>Test Image</description>
3560<foo:hello>Hi there!</foo:hello>
3561</image>
3562
3563<item>
3564<title>This is an item</title>
3565<link>http://example.com/2007/01/19</link>
3566<description>Yadda yadda yadda - R&#x26;D;</description>
3567<author>joeuser@example.com</author>
3568<category>MyCategory</category>
3569<comments>http://example.com/2007/01/19/comments.html</comments>
3570<guid isPermaLink="true">http://example.com/2007/01/19</guid>
3571<pubDate>Fri 19 Jan 2007 02:21:43 PM IST GMT</pubDate>
3572<source url="http://example.com">my brain</source>
3573<enclosure url="http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent" type="application/x-bittorrent" />
3574</item>
3575
3576</channel>
3577</rss>
3578EOF
3579
3580    eval {
3581        $rss_parser->parse($xml_text);
3582    };
3583
3584    # TEST
3585    ok ($@ =~ m{\AMalformed RSS},
3586        "Checking for thrown exception on missing version attribute"
3587    );
3588}
3589
3590{
3591    my $rss_parser = XML::RSS->new(version => "1.0");
3592
3593    my $xml_text = <<'EOF';
3594<?xml version="1.0" encoding="UTF-8"?>
3595
3596<rdf:RDF
3597 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3598 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3599 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3600 xmlns:dc="http://purl.org/dc/elements/1.1/"
3601 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3602 xmlns:my="http://purl.org/my/rss/module/"
3603 xmlns:admin="http://webns.net/mvcb/"
3604>
3605
3606<channel rdf:about="http://example.com/">
3607<title>Test 1.0 Feed</title>
3608<link>http://example.com/</link>
3609<description>To lead by example</description>
3610<dc:date>2007-01-19T14:21:18+0200</dc:date>
3611<items>
3612 <rdf:Seq>
3613  <rdf:li rdf:resource="http://example.com/2007/01/19" />
3614 </rdf:Seq>
3615</items>
3616<image rdf:resource="http://example.com/example.gif" />
3617<textinput rdf:resource="http://example.com/search.pl" />
3618</channel>
3619
3620<image rdf:about="http://example.com/example.gif" xmlns="">
3621<title>Test Image</title>
3622<url>http://example.com/example.gif</url>
3623<link>http://example.com/</link>
3624</image>
3625
3626<item rdf:about="http://example.com/2007/01/19">
3627<title>This is an item</title>
3628<link>http://example.com/2007/01/19</link>
3629<description>Yadda &#x26; yadda &#x26; yadda</description>
3630<dc:creator>joeuser@example.com</dc:creator>
3631</item>
3632
3633<textinput rdf:about="http://example.com/search.pl">
3634<title>Search</title>
3635<description>Search for an example</description>
3636<name>q</name>
3637<link>http://example.com/search.pl</link>
3638<dc:date>5 May 1977</dc:date>
3639</textinput>
3640
3641</rdf:RDF>
3642EOF
3643
3644    eval {
3645        $rss_parser->parse($xml_text);
3646    };
3647
3648    # TEST
3649    ok ($@ =~ m{\AMalformed RSS: invalid version},
3650        "Checking for thrown exception on missing version attribute"
3651    );
3652
3653}
3654
3655{
3656    my $rss_parser = XML::RSS->new(version => "1.0");
3657
3658    $rss_parser->parse(<<'EOF');
3659<?xml version="1.0" encoding="UTF-8"?>
3660
3661<rdf:RDF
3662 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3663 xmlns="http://purl.org/rss/1.0/"
3664 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3665 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3666 xmlns:dc="http://purl.org/dc/elements/1.1/"
3667 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3668 xmlns:admin="http://webns.net/mvcb/"
3669 xmlns:foo="http://foobar.tld/foobardom/"
3670>
3671
3672<channel rdf:about="http://freshmeat.net">
3673<title>freshmeat.net</title>
3674<link>http://freshmeat.net</link>
3675<description>Linux software</description>
3676<items>
3677 <rdf:Seq>
3678  <rdf:li rdf:resource="http://freshmeat.net/news/1999/06/21/930003829.html" />
3679  <rdf:li rdf:resource="http://jungle.tld/Enter/" />
3680 </rdf:Seq>
3681</items>
3682<taxo:topics>
3683  <rdf:Bag>
3684    <rdf:li resource="Elastic" />
3685    <rdf:li resource="Plastic" />
3686    <rdf:li resource="stochastic" />
3687    <rdf:li resource="dynamic^^K" />
3688  </rdf:Bag>
3689</taxo:topics>
3690</channel>
3691
3692<item rdf:about="http://freshmeat.net/news/1999/06/21/930003829.html">
3693<title>GTKeyboard 0.85</title>
3694<link>http://freshmeat.net/news/1999/06/21/930003829.html</link>
3695<item rdf:about="http://fooque.tld/">
3696</item>
3697</item>
3698</rdf:RDF>
3699EOF
3700
3701    # TEST
3702    is (scalar(@{$rss_parser->{items}}), 1, "Parse 1.0 with nested <item>");
3703}
3704
3705{
3706    my $rss_parser = XML::RSS->new(version => "2.0");
3707
3708my $xml_text = <<'EOF';
3709<?xml version="1.0" encoding="UTF-8"?>
3710
3711<rss version="2.0"
3712 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
3713 xmlns:foo="http://foo.tld/foobar/"
3714 xmlns:anno="http://purl.org/rss/1.0/modules/annotate/"
3715>
3716
3717<channel>
3718<title>Test 2.0 Feed</title>
3719<link>http://example.com/</link>
3720<description>Lambda</description>
3721<anno:reference resource="Aloha" />
3722
3723</channel>
3724</rss>
3725EOF
3726
3727    $rss_parser->parse($xml_text);
3728
3729    my $channel = $rss_parser->{channel};
3730
3731    # Sanitize the channel out of uninitialised keys.
3732    foreach my $field (qw(
3733        category
3734        channel
3735        cloud
3736        copyright
3737        docs
3738        generator
3739        image
3740        language
3741        lastBuildDate
3742        managingEditor
3743        pubDate
3744        skipDays
3745        skipHours
3746        textinput
3747        ttl
3748        webMaster
3749    ))
3750    {
3751        delete $channel->{$field};
3752    }
3753    # TEST
3754    is_deeply($channel,
3755        {
3756            title => "Test 2.0 Feed",
3757            link => "http://example.com/",
3758            description => "Lambda",
3759            "http://purl.org/rss/1.0/modules/annotate/" =>
3760            {
3761                reference => "Aloha",
3762            },
3763        },
3764        "Testing for non-moduled-namespaced element inside the channel."
3765    );
3766}
3767
3768{
3769    my $rss_parser = XML::RSS->new(version => "2.0");
3770
3771my $xml_text = <<'EOF';
3772<?xml version="1.0" encoding="UTF-8"?>
3773
3774<rss version="2.0"
3775 xmlns:blogChannel="http://backend.userland.com/blogChannelModule"
3776 xmlns:foo="http://foo.tld/foobar/"
3777 xmlns:anno="http://purl.org/rss/1.0/modules/annotate/"
3778>
3779
3780<channel>
3781<title>Test 2.0 Feed</title>
3782<link>http://example.com/</link>
3783<description>Lambda</description>
3784
3785
3786<item>
3787<title>This is an item</title>
3788<link>http://example.com/2007/01/19</link>
3789<description>Yadda yadda yadda</description>
3790<author>joeuser@example.com</author>
3791<anno:reference resource="Aloha" />
3792</item>
3793
3794</channel>
3795
3796</rss>
3797EOF
3798
3799    $rss_parser->parse($xml_text);
3800
3801    my $item = $rss_parser->{items}->[0];
3802
3803    # Sanitize the channel out of uninitialised keys.
3804    foreach my $field (qw(
3805        item
3806    ))
3807    {
3808        delete $item->{$field};
3809    }
3810    # TEST
3811    is_deeply($item,
3812        {
3813            title => "This is an item",
3814            link => "http://example.com/2007/01/19",
3815            description => "Yadda yadda yadda",
3816            author => "joeuser\@example.com",
3817            "http://purl.org/rss/1.0/modules/annotate/" =>
3818            {
3819                reference => "Aloha",
3820            },
3821        },
3822        "Testing for non-moduled-namespaced element inside an item."
3823    );
3824}
3825
3826{
3827    my $rss_parser = XML::RSS->new(version => "1.0");
3828
3829    $rss_parser->parse(<<'EOF');
3830<?xml version="1.0" encoding="UTF-8"?>
3831
3832<rdf:RDF
3833 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
3834 xmlns="http://purl.org/rss/1.0/"
3835 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3836 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
3837 xmlns:dc="http://purl.org/dc/elements/1.1/"
3838 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
3839 xmlns:my="http://purl.org/my/rss/module/"
3840 xmlns:admin="http://webns.net/mvcb/"
3841>
3842
3843<channel rdf:about="http://example.com/">
3844<title>Test 1.0 Feed</title>
3845<link>http://example.com/</link>
3846<description>To lead by example</description>
3847<dc:date>2007-01-19T14:21:18+0200</dc:date>
3848<items>
3849 <rdf:Seq>
3850  <rdf:li rdf:resource="http://example.com/2007/01/19" />
3851 </rdf:Seq>
3852</items>
3853<image rdf:resource="http://example.com/example.gif" />
3854<textinput rdf:resource="http://example.com/search.pl" />
3855</channel>
3856
3857<image rdf:about="http://example.com/example.gif" xmlns="">
3858<title>Test Image</title>
3859<url>http://example.com/example.gif</url>
3860<link>http://example.com/</link>
3861<dc:date>5 Sep 2006</dc:date>
3862</image>
3863
3864<item rdf:about="http://example.com/2007/01/19">
3865<title>This is an item</title>
3866<link>http://example.com/2007/01/19</link>
3867<description>Yadda &#x26; yadda &#x26; yadda</description>
3868<dc:creator>joeuser@example.com</dc:creator>
3869<admin:generatorAgent resource="XmlRssGenKon" />
3870</item>
3871
3872<textinput rdf:about="http://example.com/search.pl">
3873<title>Search</title>
3874<description>Search for an example</description>
3875<name>q</name>
3876<link>http://example.com/search.pl</link>
3877</textinput>
3878
3879</rdf:RDF>
3880EOF
3881
3882    # TEST
3883    is ($rss_parser->{items}->[0]->{admin}->{generatorAgent},
3884        "XmlRssGenKon",
3885        "Parsing 1.0 - known module rdf_resource_field",
3886    );
3887}
3888
3889{
3890    my $rss = create_item_rss(
3891        {
3892            version => "2.0",
3893            item_params =>
3894            [
3895                media => {
3896                    title    => "media title",
3897                    text     => "media text",
3898                    content  => {
3899                        url    => "http://somrurl.org/img/foo.jpg",
3900                        type   => "image/jpeg",
3901                        height => "100",
3902                        width  => "100",
3903                    },
3904                },
3905            ],
3906        }
3907    );
3908    $rss->add_module(prefix=>'media', uri=>'http://search.yahoo.com/mrss/');
3909
3910    # TEST
3911    contains($rss,
3912        qq{<media:content height="100" type="image/jpeg" url="http://somrurl.org/img/foo.jpg" width="100"/>\n},
3913        "namespaces with attributes are rendered correctly. (bug #25336)"
3914    );
3915}
3916
3917{
3918    my $xml;
3919
3920    {
3921        my $rss = XML::RSS->new( 'xml:base' => 'http://example.com/' );
3922
3923        # TEST
3924        ok($rss, "Created new rss");
3925
3926        # TEST
3927        is($rss->{'xml:base'}, 'http://example.com/', 'Got base');
3928
3929        $rss->{'xml:base'} = 'http://foo.com/';
3930
3931        $rss->channel(
3932            description => "Foo",
3933            title => "Hi",
3934            link => "http://www.tld/",
3935        );
3936
3937        # TEST
3938        ok($rss->add_item(
3939            title => 'foo',
3940            'xml:base' => "http://foo.com/archive/",
3941            description => {
3942                content    => "Bar",
3943                'xml:base' => "http://foo.com/archive/1.html",
3944            }
3945        ), "Added item");
3946
3947        $xml = $rss->as_rss_2_0();
3948
3949        # TEST
3950        ok($xml, "Got xml");
3951
3952        # TEST
3953        output_contains(
3954            $xml,
3955            qq{<rss version="2.0"\n xml:base="http://foo.com/"},
3956            "Found rss base"
3957        );
3958
3959        # TEST
3960        output_contains (
3961            $xml,
3962            qq{<item xml:base="http://foo.com/archive/"},
3963            "Found item base"
3964        );
3965
3966        # TEST
3967        output_contains (
3968            $xml,
3969            qq{<description xml:base="http://foo.com/archive/1.html"},
3970            "Found description base"
3971        );
3972    }
3973
3974    {
3975        my $rss = XML::RSS->new;
3976
3977        # TEST
3978        ok($rss->parse($xml), "Reparsed xml");
3979
3980        # TEST
3981        is(
3982            $rss->{'xml:base'},
3983            'http://foo.com/',
3984            "Found parsed rss base"
3985        );
3986
3987        # TEST
3988        is (scalar(@{$rss->{items}}), 1, "Got 1 item");
3989
3990        my $item = $rss->{items}->[0];
3991
3992        # TEST
3993        is($item->{'xml:base'}, 'http://foo.com/archive/',
3994            "Found parsed item base"
3995        );
3996
3997        # TEST
3998        is($item->{description}, "Bar",
3999            "description is a string - not a hash ref with correct content"
4000        );
4001    }
4002
4003    {
4004        my $rss = XML::RSS->new;
4005
4006        # TEST
4007        ok($rss->parse($xml, {hashrefs_instead_of_strings => 1}),
4008            "Reparsed xml"
4009        );
4010
4011        # TEST
4012        is(
4013            $rss->{'xml:base'},
4014            'http://foo.com/',
4015            "Found parsed rss base"
4016        );
4017
4018        # TEST
4019        is (scalar(@{$rss->{items}}), 1, "Got 1 item");
4020
4021        my $item = $rss->{items}->[0];
4022
4023        # TEST
4024        is($item->{'xml:base'}, 'http://foo.com/archive/',       "Found parsed item base");
4025        # TEST
4026        is($item->{description}->{'xml:base'}, 'http://foo.com/archive/1.html', "Found parsed description base");
4027    }
4028
4029}
4030
4031{
4032    my $xml;
4033
4034    {
4035        my $rss = XML::RSS->new( 'xml:base' => 'http://example.com/' );
4036
4037        # TEST
4038        ok($rss, "Created new rss");
4039
4040        # TEST
4041        is($rss->{'xml:base'}, 'http://example.com/', 'Got base');
4042
4043        $rss->{'xml:base'} = 'http://foo.com/';
4044
4045        $rss->channel(
4046            title => "freshmeat.net",
4047            link  => "http://freshmeat.net",
4048            description => "the one-stop-shop for all your Linux software needs",
4049            );
4050
4051        # TEST
4052        ok($rss->add_item(
4053            title => 'foo',
4054            'xml:base' => "http://foo.com/archive/",
4055            description => {
4056                content    => "Bar",
4057                'xml:base' => "<H&G>",
4058            }
4059        ), "Added item");
4060
4061        $xml = $rss->as_rss_2_0();
4062
4063        # TEST
4064        ok($xml, "Got xml");
4065
4066        # TEST
4067        output_contains (
4068            $xml,
4069            qq{<description xml:base="&#x3C;H&#x26;G&#x3E;"},
4070            "description was properly encoded"
4071        );
4072    }
4073}
4074
4075{
4076    my $rss = create_rss_1({
4077        version => "1.0",
4078        image_params =>
4079        [
4080            eloq =>
4081            [
4082                { 'el' => 'grow', 'val' => "There" },
4083                { 'el' => 'grow', 'val' => "Position", },
4084                { 'el' => 'show', 'val' => "and tell", },
4085                { 'el' => 'show', 'val' => "must go on", },
4086            ],
4087        ],
4088    });
4089
4090    $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
4091    # TEST
4092    contains($rss, "<image rdf:about=\"0\">\n" .
4093        "<title>freshmeat.net</title>\n" .
4094        "<url>0</url>\n" .
4095        "<link>http://freshmeat.net/</link>\n" .
4096        "<eloq:grow>There</eloq:grow>\n" .
4097        "<eloq:grow>Position</eloq:grow>\n" .
4098        "<eloq:show>and tell</eloq:show>\n" .
4099        "<eloq:show>must go on</eloq:show>\n" .
4100        "</image>",
4101        'Multiple values for the same key in a module, usign an array ref'
4102    );
4103
4104    my $parsed_rss = XML::RSS->new(version => '1.0');
4105    $parsed_rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/");
4106    $parsed_rss->parse($rss->as_string(), { modules_as_arrays => 1, });
4107
4108    # TEST
4109    is_deeply(
4110        $parsed_rss->{'image'}->{'eloq'},
4111        [
4112            { 'el' => 'grow', 'val' => "There" },
4113            { 'el' => 'grow', 'val' => "Position", },
4114            { 'el' => 'show', 'val' => "and tell", },
4115            { 'el' => 'show', 'val' => "must go on", },
4116        ],
4117        "modules_as_arrays parsed the namespace into an array."
4118    );
4119}
4120
4121{
4122    my $rss = create_channel_rss({
4123        version => "1.0",
4124    });
4125
4126    $rss->add_item(
4127        title => "In the Dublin Core Jungle",
4128        link => "http://jungle.tld/Enter/",
4129        dc => {
4130            subject => ['tiger', 'elephant', 'snake',],
4131            language => "en-GB",
4132        },
4133    );
4134
4135    # TEST
4136    contains($rss, "<item rdf:about=\"http://jungle.tld/Enter/\">\n" .
4137        "<title>In the Dublin Core Jungle</title>\n" .
4138        "<link>http://jungle.tld/Enter/</link>\n" .
4139        "<dc:language>en-GB</dc:language>\n" .
4140        "<dc:subject>tiger</dc:subject>\n" .
4141        "<dc:subject>elephant</dc:subject>\n" .
4142        "<dc:subject>snake</dc:subject>\n" .
4143        "</item>\n",
4144        "1.0 - item/multiple dc:subject's"
4145    );
4146
4147    my $parsed_rss = XML::RSS->new(version => '1.0');
4148
4149    $parsed_rss->parse($rss->as_string());
4150
4151    # TEST
4152    is_deeply (
4153        $parsed_rss->{'items'}->[1]->{'dc'}->{'subject'},
4154        [qw(tiger elephant snake)],
4155        "Properly parsed dc:subject into an array.",
4156    );
4157
4158    # TEST
4159    is(
4160        $parsed_rss->{'items'}->[1]->{'dc'}->{'language'},
4161        "en-GB",
4162        "Properly parsed dc:language.",
4163    );
4164}
4165
4166{
4167    my $rss = create_skipDays_rss({
4168            version => "2.0",
4169            skipDays_params => [ day => [qw(Sunday Thursday Saturday)] ],
4170        });
4171    # TEST
4172    contains($rss, ("<skipDays>\n"
4173        . "<day>Sunday</day>\n"
4174        . "<day>Thursday</day>\n"
4175        . "<day>Saturday</day>\n"
4176        . "</skipDays>\n"),
4177        "Generate skipDays with multiple values (array)."
4178    );
4179}
4180
4181
4182{
4183    my $rss = create_skipHours_rss({
4184            version => "2.0",
4185            skipHours_params => [ hour => [qw(5 10 16)] ],
4186        });
4187    # TEST
4188    contains($rss, ("<skipHours>\n"
4189        . "<hour>5</hour>\n"
4190        . "<hour>10</hour>\n"
4191        . "<hour>16</hour>\n"
4192        . "</skipHours>\n"),
4193        "2.0 - skipHours/hour == 0"
4194    );
4195}
4196
4197
4198{
4199    my $rss = create_item_with_0_rss({version => "2.0",
4200            item_params =>
4201            [
4202                title => "Foo&Bar",
4203                link => "http://www.mytld/",
4204                category => ["OneCat", "TooCat", "3Kitties"],
4205            ],
4206        }
4207    );
4208
4209    # TEST
4210    contains(
4211        $rss,
4212        ("<item>\n" .
4213         "<title>Foo&#x26;Bar</title>\n" .
4214         "<link>http://www.mytld/</link>\n" .
4215         "<category>OneCat</category>\n" .
4216         "<category>TooCat</category>\n" .
4217         "<category>3Kitties</category>\n" .
4218         "</item>"
4219         ),
4220        "2.0 - item/multiple-category's",
4221    );
4222}
4223
4224{
4225    # Here we create an RSS 2.0 object and render it as the output
4226    # version "3.5" in order to test that version 1.0 is the default
4227    # version for output.
4228    my $rss = create_channel_rss({
4229            version => "2.0",
4230            channel_params =>
4231            [category => [qw(OneCat TooManyCats KittensGalore)]],
4232            omit_date => 1,
4233        });
4234    # TEST
4235    contains($rss, ("<channel>\n" .
4236        "<title>freshmeat.net</title>\n" .
4237        "<link>http://freshmeat.net</link>\n" .
4238        "<description>Linux software</description>\n" .
4239        "<category>OneCat</category>\n" .
4240        "<category>TooManyCats</category>\n" .
4241        "<category>KittensGalore</category>\n" .
4242        "\n" .
4243        "<item>\n"),
4244        "Multiple channel/category elements"
4245    );
4246}
4247
4248