# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl 1.t' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test::More tests => 35; use XML::LibXML; use Algorithm::Diff qw(diff); BEGIN { use_ok('XML::Diff') }; ######################### # Insert your test code below, the Test::More module is use()ed here so read # its man page ( perldoc Test::More ) for help writing this test script. my $xml = { 'update_text' => [ qq{ blah blah blah }, qq{ brah blah brah }, ], 'update_text_add' => [ qq{ }, qq{ brah blah brah }, ], 'update_text_remove' => [ qq{ blah blah blah }, qq{ }, ], 'update_text_chain' => [ qq{ a c }, qq{ a x }, ], 'update_text_chain2' => [ qq{ b d }, qq{ b x }, ], 'update_text_chain_mix' => [ qq{ b d }, qq{ b f d }, ], 'update_text_chain_add_start' => [ qq{ b d }, qq{ a b d }, ], 'update_text_chain_add_end' => [ qq{ ab }, qq{ abd }, ], 'update_attribute_add' => [ qq{ blah blah blah }, qq{ blah blah blah }, ], 'update_attribute_delete' => [ qq{ blah blah blah }, qq{ blah blah blah }, ], 'update_mixed' => [ qq{ blah blah blah }, qq{ blah brah blah }, ], 'update_attribute_change' => [ qq{ blah blah blah }, qq{ blah blah blah }, ], 'add_at_end' => [ qq{ }, qq{ }, ], 'add_at_start' => [ qq{ }, qq{ }, ], 'add_in_the_middle' => [ qq{ }, qq{ }, ], 'add_random' => [ qq{ }, qq{ }, ], 'delete_at_end' => [ qq{ }, qq{ }, ], 'delete_at_start' => [ qq{ }, qq{ }, ], 'delete_in_middle' => [ qq{ }, qq{ }, ], 'delete_random' => [ qq{ }, qq{ }, ], 'add_delete' => [ qq{ }, qq{ }, ], 'add_delete_random' => [ qq{ }, qq{ }, ], 'local_move_random' => [ qq{ }, qq{ }, ], 'local_move_to_end_to_end' => [ qq{ }, qq{ }, ], 'local_move_with_add' => [ qq{ }, qq{ }, ], 'local_move_with_delete' => [ qq{ }, qq{ }, ], 'tree_move_single_node' => [ qq{ }, qq{ }, ], 'tree_move_subtree' => [ qq{ }, qq{ }, ], 'tree_move_with_local_move' => [ qq{ }, qq{ }, ], }; my $test_file1 = 't/xml/test1.xml'; my $test_file2 = 't/xml/test2.xml'; # this excercises the different methods and input formats instantiate(); load_file($test_file1); load_string($test_file1); load_libxml_doc($test_file1); load_libxml_element($test_file1); # this tests that our Diff and Patch work test_xml( 'update_text' ); test_xml( 'update_text_add' ); test_xml( 'update_text_remove' ); test_xml( 'update_text_chain' ); test_xml( 'update_text_chain2' ); test_xml( 'update_text_chain_mix' ); test_xml( 'update_text_chain_add_start' ); test_xml( 'update_text_chain_add_end' ); test_xml( 'update_attribute_add' ); test_xml( 'update_attribute_delete' ); test_xml( 'update_attribute_change' ); test_xml( 'update_mixed' ); test_xml( 'add_at_end' ); test_xml( 'add_at_start' ); test_xml( 'add_in_the_middle' ); test_xml( 'add_random' ); test_xml( 'delete_at_end' ); test_xml( 'delete_at_start' ); test_xml( 'delete_in_middle' ); test_xml( 'delete_random' ); test_xml( 'add_delete' ); test_xml( 'add_delete_random' ); test_xml( 'local_move_random' ); test_xml( 'local_move_to_end_to_end' ); test_xml( 'local_move_with_add' ); test_xml( 'local_move_with_delete' ); test_xml( 'tree_move_single_node' ); test_xml( 'tree_move_subtree' ); test_xml( 'tree_move_with_local_move' ); exit; sub instantiate { my $diff = XML::Diff->new(); ok( defined $diff,'instatiated XML::Diff' ); } sub load_file { my $test_file = shift; my $diff = XML::Diff->new(); my $success; if( !-e $test_file ) { diag( "test file '$test_file' does not exist" ); } elsif( defined $diff->_getDoc('old',$test_file) ) { $success = 1; } ok( $success, "load XML from file" ); } sub load_string { my $test_file = shift; my $diff = XML::Diff->new(); my $success; if( !-e $test_file ) { diag( "test file '$test_file' does not exist" ); } else { open( FH, $test_file ); my @test_string = ; my $test_string = join('',@test_string); close FH; if( defined $diff->_getDoc('old',$test_string) ) { $success = 1; } } ok( $success, "load XML from string" ); } sub load_libxml_doc { my $test_file = shift; my $diff = XML::Diff->new(); my $success; if( !-e $test_file ) { diag( "test file '$test_file' does not exist" ); } else { my $parser = XML::LibXML->new(); if( !$parser ) { diag( "unable to create LibXML parser" ); } else { $parser->keep_blanks(0); my $doc = $parser->parse_file( $test_file ); if( !$doc ) { diag( "unable to parse file '$test_file' with libXML" ); } elsif( defined $diff->_getDoc('old',$doc) ) { $success = 1; } } } ok( $success, "load XML from XML::LibXML Document" ); } sub load_libxml_element { my $test_file = shift; my $diff = XML::Diff->new(); my $success; if( !-e $test_file ) { diag( "test file '$test_file' does not exist" ); } else { my $parser = XML::LibXML->new(); if( !$parser ) { diag( "unable to create LibXML parser" ); } else { $parser->keep_blanks(0); my $doc = $parser->parse_file( $test_file ); if( !$doc ) { diag( "unable to parse file '$test_file' with libXML" ); } else { my $root = $doc->documentElement(); if( !$root ) { diag( "unable to get root element from XML::LibXML::Document" ); } elsif( defined $diff->_getDoc('old',$root) ) { $success = 1; } } } } ok( $success, "load XML from XML::LibXML Element" ); } sub test_xml { my $test_name = shift; my($old,$new) = @{$xml->{$test_name}}; my $diff = XML::Diff->new(); my $diffgram = $diff->compare( -old => $old, -new => $new, ); my $patched = $diff->patch( -old => $old, -diffgram => $diffgram, ); my $parser = XML::LibXML->new(); $parser->keep_blanks(0); # we force our XML through the parser so we know the differences aren't due # to formatting issues my $doc_old = $parser->parse_string( $old ); my $doc_new = $parser->parse_string( $new ); # we sort our attributes so that a text domain diff doesn't mistake # attribute mis-ordering for actual differences sort_attributes( $doc_old ); sort_attributes( $doc_new ); sort_attributes( $patched ); my @target = split(/\n/,$doc_new->toString(1)); my @patched = split(/\n/,$patched->toString(1)); my @diffs = diff( \@target, \@patched ); my $success; if( ! @diffs ) { $success = 1; } ok( $success, "testing diff case '$test_name'" ); } sub sort_attributes { my $doc = shift; my $root = $doc->documentElement(); dig_sort($root); } sub dig_sort { my $node = shift; if( $node->nodeType == 3 ) { return; } else { foreach my $child ( $node->childNodes() ) { dig_sort( $child ); } my @attributes = $node->attributes(); foreach (@attributes) { $node->removeAttribute( $_->name ); } foreach ( sort {$a->name cmp $b->name} @attributes ) { $node->setAttribute( $_->name, $_->value ); } } }