# YAML test runner for XML::Validator::Schema. Takes .yml files
# containing a schema and applies it to one or more files evaluating
# the results as specified. Just look at t/*.yml and you'll get the
# idea.
package TestRunner;
use strict;
use warnings;
use Test::Builder;
my $Test = Test::Builder->new;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = ('test_yml', 'foreach_parser', 'test_yml_xerces');
use YAML qw(LoadFile);
use XML::SAX::ParserFactory;
use XML::Validator::Schema;
use XML::SAX;
use Cwd qw(cwd);
use Data::Dumper;
sub foreach_parser (&) {
my $tests = shift;
my @parsers = map { $_->{Name} } (@{XML::SAX->parsers});
@parsers = ($ENV{XMLVS_TEST_PARSER}) if exists $ENV{XMLVS_TEST_PARSER};
# remove XML::LibXML::SAX::Parser and XML::SAX::RTF. Neither works.
@parsers = grep { $_ ne 'XML::LibXML::SAX::Parser' and
$_ ne 'XML::SAX::RTF' } @parsers;
# run tests with all available parsers
foreach my $pkg (@parsers) {
$XML::SAX::ParserPackage = $pkg;
print STDERR "\n\n ======> Testing against $pkg ".
"<======\n\n";
$tests->();
}
}
sub test_yml {
my $file = shift;
my ($prefix) = $file =~ /(\w+)\.yml$/;
my @data = LoadFile($file);
# write out the schema file
my $xsd = shift @data;
open(my $fh, '>', "t/$prefix.xsd") or die $!;
print $fh $xsd;
close($fh) or die $!;
my $num = 0;
while(@data) {
my $xml = shift @data;
my $result = shift @data;
chomp($result);
$num++;
# run the xml through the parser
eval {
my $parser = XML::SAX::ParserFactory->parser(
Handler => XML::Validator::Schema->new(cache => 1,
file => "t/$prefix.xsd"));
$parser->parse_string($xml);
};
my $err = $@;
if ($result =~ m!^FAIL\s*(?:/(.*?)/)?$!) {
my $re = $1;
$Test->ok($err, "$prefix.yml: block $num should fail validation");
if ($re) {
if ($err) {
$Test->like($err, qr/$re/,
"$prefix.yml: block $num should fail matching /$re/");
} else {
$Test->ok(0, "$prefix.yml: block $num should fail matching /$re/");
}
}
} else {
$Test->ok(not($err), "$prefix.yml: block $num should pass validation");
print STDERR "$prefix.yml: block $num ====> $@\n" if $err;
}
}
# cleanup
unlink "t/$prefix.xsd" or die $!;
}
sub test_yml_xerces {
my $file = shift;
my ($prefix) = $file =~ /(\w+)\.yml$/;
my @data = LoadFile($file);
my $old_dir = cwd;
chdir("t") or die "Unable to chdir to t/: $!";
# write out the schema file
my $xsd = shift @data;
open(my $fh, '>', "$prefix.xsd") or die $!;
print $fh $xsd;
close($fh) or die $!;
my $num = 0;
while(@data) {
my $xml = shift @data;
my $result = shift @data;
chomp($result);
$num++;
# fixup $xml to refer to schema
$xml =~ s!<([^?].*?)(/?)>!<$1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="$prefix.xsd"$2>!;
# write the xml into a temp file
open(XML, '>', "_$prefix.xml") or die $!;
print XML $xml;
close XML;
# run the xml through the parser
my $out = `$ENV{XERCES_DOMCOUNT} -v=always -n -s -f _$prefix.xml 2>&1`;
my $err;
if ($out =~ /Error/) {
$out =~ s!Errors occurred, no output available!!g;
$out =~ s!^\s+!!;
$out =~ s{\s+$}{};
$err = $out;
}
if ($result =~ m!^FAIL\s*(?:/(.*?)/)?$!) {
print STDERR "==> $ENV{XERCES_DOMCOUNT} -v=always -n -s -f _$prefix.xml:\nout\n" unless $err;
$Test->ok($err, "$prefix.yml: block $num should fail validation");
} else {
print STDERR "==> $ENV{XERCES_DOMCOUNT} -v=always -n -s -f _$prefix.xml:\n$out\n" if $err;
$Test->ok(not($err), "$prefix.yml: block $num should pass validation");
}
}
# cleanup
unlink "$prefix.xsd" or die $!;
unlink "_$prefix.xml" or die $!;
chdir($old_dir);
}
1;