# 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 );
}
}
}