Files
oddmuse/t/test.pl
Alex Schroeder c65d1b8274 (xpath_do): Don't be confused by the new xmlns
attribute in the html element.
2007-11-13 20:21:10 +00:00

237 lines
6.2 KiB
Perl
Executable File

# Copyright (C) 2004, 2005, 2006 Alex Schroeder <alex@emacswiki.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.
# 59 Temple Place, Suite 330
# Boston, MA 02111-1307 USA
package OddMuse;
use lib '.';
use XML::LibXML;
use Encode;
# Import the functions
$RunCGI = 0; # don't print HTML on stdout
$UseConfig = 0; # don't read module files
require 'wiki.pl';
Init();
use vars qw($redirect);
my $resultfile = "/tmp/test-markup-result-$$";
undef $/;
$| = 1; # no output buffering
sub url_encode {
my $str = shift;
return '' unless $str;
my @letters = split(//, $str);
my @safe = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '-', '_', '.'); # shell metachars are unsafe
foreach my $letter (@letters) {
my $pattern = quotemeta($letter);
if (not grep(/$pattern/, @safe)) {
$letter = sprintf("%%%02x", ord($letter));
}
}
return join('', @letters);
}
sub update_page {
my ($id, $text, $summary, $minor, $admin, @rest) = @_;
my $pwd = $admin ? 'foo' : 'wrong';
$id = url_encode($id);
$text = url_encode($text);
$summary = url_encode($summary);
$minor = $minor ? 'on' : 'off';
my $rest = join(' ', @rest);
$redirect = `perl wiki.pl 'Save=1' 'title=$id' 'summary=$summary' 'recent_edit=$minor' 'text=$text' 'pwd=$pwd' $rest`;
$output = `perl wiki.pl action=browse id=$id $rest`;
if ($redirect =~ /^Status: 302 /) {
# just in case a new page got created or NearMap or InterMap
$IndexHash{$id} = 1;
@IndexList = sort(keys %IndexHash);
ReInit($id); # if $id eq $InterMap, we need it to be in the $IndexHash before running ReInit()
}
return $output;
}
sub get_page {
open(F,"perl wiki.pl @_ |");
my $output = <F>;
close F;
return $output;
}
sub name {
$_ = shift;
s/\n/\\n/g;
$_ = substr($_, 0, 60) . '...' if length > 63;
return $_;
}
sub newlines {
my @strings = @_;
return map { s/\\n/\n/g; $_; } @strings;
}
# alternating input and output strings for applying rules
sub run_tests {
# translate embedded newlines (other backslashes remain untouched)
my @tests = newlines(@_);
my ($input, $output);
while (($input, $output, @tests) = @tests) {
my $result = apply_rules($input);
is($result, $output, name($input));
}
}
sub apply_rules {
my $input = shift;
local *STDOUT;
$output = '';
open(STDOUT, '>', \$output) or die "Can't open memory file: $!";
$FootnoteNumber = 0;
ApplyRules(QuoteHtml($input), 1);
return $output;
}
# alternating input and output strings for applying macros instead of rules
sub run_macro_tests {
# translate embedded newlines (other backslashes remain untouched)
my %test = map { s/\\n/\n/g; $_; } @_;
# Note that the order of tests is not specified!
foreach my $input (keys %test) {
$_ = $input;
foreach my $macro (@MyMacros) { &$macro; }
is($_, $test{$input}, $input);
}
}
# one string, many tests
sub test_page {
my $page = shift;
foreach my $str (@_) {
like($page, qr($str), name($str));
}
}
# one string, many negative tests
sub test_page_negative {
my $page = shift;
foreach my $str (@_) {
unlike($page, qr($str), name("not $str"));
}
}
sub xpath_do {
my ($check, $message, $page, @tests) = @_;
$page =~ s/^.*?(<html)/$1/s; # strip headers
my $page_shown = 0;
my $parser = XML::LibXML->new();
my $doc;
my $result;
SKIP: {
eval { $doc = $parser->parse_html_string($page) };
skip("Cannot parse ".name($page).": $@", $#tests + 1) if $@;
foreach my $test (@tests) {
my $nodelist;
eval { $nodelist = $doc->findnodes($test) };
if ($@) {
fail(&$check(1) ? "$test: $@" : "not $test: $@");
} elsif (ok(&$check($nodelist->size()), name(&$check(1) ? $test : "not $test"))) {
$result .= $nodelist->string_value();
} else {
$page =~ s/^.*?<body/<body/s;
diag($message, substr($page,0,30000)) unless $page_shown;
$page_shown = 1;
}
}
}
return $result; # return string_value() of all found nodes
}
sub xpath_test {
xpath_do(sub { shift > 0; }, "No Matches\n", @_);
}
sub negative_xpath_test {
xpath_do(sub { shift == 0; }, "Unexpected Matches\n", @_);
}
sub xpath_run_tests {
# translate embedded newlines (other backslashes remain untouched)
my @tests = newlines(@_);
my ($input, $output);
while (($input, $output, @tests) = @tests) {
my $result = apply_rules($input);
xpath_test("<div>$result</div>", $output);
}
}
sub remove_rule {
my $rule = shift;
my @list = ();
my $found = 0;
foreach my $item (@MyRules) {
if ($item ne $rule) {
push @list, $item;
} else {
$found = 1;
}
}
die "Rule not found" unless $found;
@MyRules = @list;
}
sub add_module {
my $mod = shift;
mkdir $ModuleDir unless -d $ModuleDir;
my $dir = `/bin/pwd`;
chop($dir);
symlink("$dir/modules/$mod", "$ModuleDir/$mod") or die "Cannot symlink $mod: $!"
unless -l "$ModuleDir/$mod";
do "$ModuleDir/$mod";
@MyRules = sort {$RuleOrder{$a} <=> $RuleOrder{$b}} @MyRules;
}
sub remove_module {
my $mod = shift;
mkdir $ModuleDir unless -d $ModuleDir;
unlink("$ModuleDir/$mod") or die "Cannot unlink: $!";
}
sub clear_pages {
system('/bin/rm -rf /tmp/oddmuse');
die "Cannot remove /tmp/oddmuse!\n" if -e '/tmp/oddmuse';
mkdir '/tmp/oddmuse';
open(F,'>/tmp/oddmuse/config');
print F "\$AdminPass = 'foo';\n";
# this used to be the default in earlier CGI.pm versions
print F "\$ScriptName = 'http://localhost/wiki.pl';\n";
print F "\$SurgeProtection = 0;\n";
close(F);
$ScriptName = 'http://localhost/test.pl'; # different!
$IndexInit = 0;
%IndexHash = ();
$InterSiteInit = 0;
%InterSite = ();
$NearSiteInit = 0;
%NearSite = ();
%NearSearch = ();
}
1;