# $Id$ use strict; use warnings; use lib './t/lib'; use Counter; use Stacker; # Should be 56 use Test::More tests => 56; use XML::LibXML; use IO::File; my $read_hash_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $h = shift; my $buflen = shift; my $id = $h->{line}; $h->{line} += 1; my $rv= $h->{lines}->[$id]; $rv = "" unless defined $rv; $inc_cb->(); return $rv; }; } } ); my $read_file_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $h = shift; my $buflen = shift; my $rv = undef; $inc_cb->(); my $n = $h->read( $rv , $buflen ); return $rv; }; } } ); my $close_file_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $h = shift; $inc_cb->(); $h->close(); return 1; }; } } ); my $close_xml_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $dom = shift; undef $dom; $inc_cb->(); return 1; }; } } ); my $open_xml_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $uri = shift; my $dom = XML::LibXML->new->parse_string(q{barbar}); if ($dom) { $inc_cb->(); } return $dom; }; }, } ); my $close_hash_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $h = shift; undef $h; $inc_cb->(); return 1; }; } } ); my $open_hash_counter = Counter->new( { gen_cb => sub { my $inc_cb = shift; return sub { my $uri = shift; my $hash = { line => 0, lines => [ "", "bar", "", "..", "" ], }; $inc_cb->(); return $hash; }; } } ); my $open_file_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $uri = shift; if (! open (my $file, '<', ".$uri")) { die "Could not open file '.$uri'!"; } else { $push_cb->($uri); return $file; } }; }, } ); my $match_hash_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $uri = shift; if ( $uri =~ /^\/libxml\// ){ $push_cb->({ verdict => 1, uri => $uri, }); return 1; } else { return; } }; }, } ); my $match_file_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $uri = shift; my $verdict = (( $uri =~ /^\/example\// ) ? 1 : 0); if ($verdict) { $push_cb->({ verdict => $verdict, uri => $uri, }); } return $verdict; }; }, } ); my $match_hash2_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $uri = shift; if ( $uri =~ /^\/example\// ){ $push_cb->({ verdict => 1, uri => $uri, }); return 1; } else { return 0; } }; }, } ); my $match_xml_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $uri = shift; if ( $uri =~ /^\/xmldom\// ){ $push_cb->({ verdict => 1, uri => $uri, }); return 1; } else { return 0; } }; }, } ); my $read_xml_stacker = Stacker->new( { gen_cb => sub { my $push_cb = shift; return sub { my $dom = shift; my $buflen = shift; my $tmp = $dom->documentElement->findnodes('tmp')->shift; my $rv = $tmp ? $dom->toString : ""; $tmp->unbindNode if($tmp); $push_cb->($rv); return $rv; }; }, } ); # --------------------------------------------------------------------- # # multiple tests # --------------------------------------------------------------------- # { my $string = < test EOF my $icb = XML::LibXML::InputCallback->new(); # TEST ok($icb, 'XML::LibXML::InputCallback was initialized'); $icb->register_callbacks( [ $match_file_stacker->cb, $open_file_stacker->cb(), $read_file_counter->cb(), $close_file_counter->cb(), ] ); $icb->register_callbacks( [ $match_hash_stacker->cb, $open_hash_counter->cb, $read_hash_counter->cb(), $close_hash_counter->cb ] ); $icb->register_callbacks( [ $match_xml_stacker->cb, $open_xml_counter->cb, $read_xml_stacker->cb, $close_xml_counter->cb] ); my $parser = XML::LibXML->new(); $parser->expand_xinclude(1); $parser->input_callbacks($icb); my $doc = $parser->parse_string($string); # read_hash - 1,1,1,1,1 # TEST:$c=0; my $test_counters = sub { # TEST:$c++; $read_hash_counter->test(6, "read_hash() count for multiple tests"); # TEST:$c++; $read_file_counter->test(2, 'read_file() called twice.'); # TEST:$c++; $close_file_counter->test(1, 'close_file() called once.'); # TEST:$c++; $open_file_stacker->test( [ '/example/test2.xml', ], 'open_file() for URLs.', ); # TEST:$c++; $match_hash_stacker->test( [ { verdict => 1, uri => '/libxml/test2.xml',}, ], 'match_hash() for URLs.', ); # TEST:$c++; $read_xml_stacker->test( [ qq{\nbarbar\n}, '', ], 'read_xml() for multiple callbacks', ); # TEST:$c++; $match_xml_stacker->test( [ { verdict => 1, uri => '/xmldom/test2.xml', }, ], 'match_xml() one.', ); # TEST:$c++; $match_file_stacker->test( [ { verdict => 1, uri => '/example/test2.xml',}, ], 'match_file() for multiple_tests', ); # TEST:$c++; $open_hash_counter->test(1, 'open_hash() : called 1 times'); # TEST:$c++; $open_xml_counter->test(1, 'open_xml() : parse_string() successful.',); # TEST:$c++; $close_xml_counter->test(1, "close_xml() called once."); # TEST:$c++; $close_hash_counter->test(1, "close_hash() called once."); }; # TEST:$test_counters=$c; # TEST*$test_counters $test_counters->(); # This is a regression test for: # https://rt.cpan.org/Ticket/Display.html?id=51086 my $doc2 = $parser->parse_string($string); # TEST*$test_counters $test_counters->(); # TEST ok ($doc, 'parse_string() returns a doc.'); # TEST is ($doc->string_value(), "\ntest\n..\nbar..\nbarbar\n", '->string_value()', ); # TEST ok ($doc2, 'second parse_string() returns a doc.'); # TEST is ($doc2->string_value(), "\ntest\n..\nbar..\nbarbar\n", q{Second parse_string()'s ->string_value()}, ); } { my $string = < test EOF my $icb = XML::LibXML::InputCallback->new(); $icb->register_callbacks( [ $match_file_stacker->cb, $open_file_stacker->cb(), $read_file_counter->cb(), $close_file_counter->cb(), ] ); $icb->register_callbacks( [ $match_hash2_stacker->cb, $open_hash_counter->cb, $read_hash_counter->cb(), $close_hash_counter->cb() ] ); my $parser = XML::LibXML->new(); $parser->expand_xinclude(1); $parser->input_callbacks($icb); my $doc = $parser->parse_string($string); # TEST $read_hash_counter->test(12, "read_hash() count for multiple register_callbacks"); # TEST $open_file_stacker->test( [ ], 'open_file() for URLs.', ); # TEST $match_hash2_stacker->test( [ { verdict => 1, uri => '/example/test2.xml',}, { verdict => 1, uri => '/example/test3.xml',}, ], 'match_hash2() input callbacks' , ); # TEST $match_file_stacker->test( [ ], 'match_file() input callbacks' , ); # TEST is ($doc->string_value(), "\ntest\nbar..\nbar..\n", 'string_value returns fine',); # TEST $open_hash_counter->test(2, 'open_hash() : called 2 times'); # TEST $close_hash_counter->test( 2, "close_hash() called twice on two xincludes." ); $icb->unregister_callbacks( [ $match_hash2_stacker->cb, \&open_hash, $read_hash_counter->cb(), $close_hash_counter->cb] ); $doc = $parser->parse_string($string); # TEST $read_file_counter->test(4, 'read_file() called 4 times.'); # TEST $close_file_counter->test(2, 'close_file() called twice.'); # TEST $open_file_stacker->test( [ '/example/test2.xml', '/example/test3.xml', ], 'open_file() for URLs.', ); # TEST $match_hash2_stacker->test( [ ], 'match_hash2() does not match after being unregistered.' , ); # TEST $match_file_stacker->test( [ { verdict => 1, uri => '/example/test2.xml',}, { verdict => 1, uri => '/example/test3.xml',}, ], 'match_file() input callbacks' , ); # TEST is($doc->string_value(), "\ntest\n..\n\n \n \n", 'string_value() after unregister callbacks', ); } { my $string = < test EOF my $string2 = < foo..bar EOF my $icb = XML::LibXML::InputCallback->new(); # TEST ok ($icb, 'XML::LibXML::InputCallback was initialized (No. 2)'); my $open_xml2 = sub { my $uri = shift; my $parser = XML::LibXML->new; $parser->expand_xinclude(1); $parser->input_callbacks($icb); my $dom = $parser->parse_string($string2); # TEST ok ($dom, 'parse_string() inside open_xml2'); return $dom; }; $icb->register_callbacks( [ $match_xml_stacker->cb, $open_xml2, $read_xml_stacker->cb, $close_xml_counter->cb ] ); $icb->register_callbacks( [ $match_hash2_stacker->cb, $open_hash_counter->cb, $read_hash_counter->cb(), $close_hash_counter->cb ] ); my $parser = XML::LibXML->new(); $parser->expand_xinclude(1); $parser->match_callback( $match_file_stacker->cb ); $parser->open_callback( $open_file_stacker->cb() ); $parser->read_callback( $read_file_counter->cb() ); $parser->close_callback( $close_file_counter->cb() ); $parser->input_callbacks($icb); my $doc = $parser->parse_string($string); # TEST $read_hash_counter->test(6, "read_hash() count for stuff."); # TEST $read_file_counter->test(2, 'read_file() called twice.'); # TEST $close_file_counter->test(1, 'close_file() called once.'); # TEST $open_file_stacker->test( [ '/example/test2.xml', ], 'open_file() for URLs.', ); # TEST $match_hash2_stacker->test( [ { verdict => 1, uri => '/example/test2.xml',}, ], 'match_hash2() input callbacks' , ); # TEST $read_xml_stacker->test( [ qq{\n\nfoo..bar..bar\n\n}, '', ], 'read_xml() No. 2', ); # TEST $match_xml_stacker->test( [ { verdict => 1, uri => '/xmldom/test2.xml', }, ], 'match_xml() No. 2.', ); # TEST $match_file_stacker->test( [ { verdict => 1, uri => '/example/test2.xml',}, ], 'match_file() for inner callback.', ); # TEST $open_hash_counter->test(1, 'open_hash() : called 1 times'); # TEST $close_xml_counter->test(1, "close_xml() called once."); # TEST $close_hash_counter->test(1, "close_hash() called once."); # TEST is ($doc->string_value(), "\ntest\n..\n\nfoo..bar..bar\n\n", 'string_value()',); }