#!/usr/bin/env perl
# -*- mode: perl; coding: utf-8 -*-
#----------------------------------------
use strict;
use warnings qw(FATAL all NONFATAL misc);
use FindBin;
BEGIN {
if (-d (my $dir = "$FindBin::RealBin/../../../../t")) {
local (@_, $@) = $dir;
do "$dir/t_lib.pl";
die $@ if $@;
}
}
use Cwd ();
my ($app_root);
BEGIN {
if (-r __FILE__) {
# detect where app.psgi is placed.
$app_root = dirname(dirname(File::Spec->rel2abs(__FILE__)));
} else {
# older uwsgi do not set __FILE__ correctly, so use cwd instead.
$app_root = Cwd::cwd();
}
}
#----------------------------------------
use 5.010; no if $] >= 5.017011, warnings => "experimental";
use Carp;
use YATT::Lite::Util qw(ostream lexpand);
use YATT::Lite::Test::XHFTest2; # To import Item class.
use base qw(YATT::Lite::Test::XHFTest2); # XXX: Redundant, but required.
BEGIN {
foreach my $req (qw(Plack)) {
unless (eval qq{require $req}) {
plan skip_all => "$req is not installed."; exit;
}
}
}
use YATT::t::t_preload; # To make Devel::Cover happy.
my MY $tests = MY->load_tests([dir => "$FindBin::Bin/../html"]
, @ARGV ? @ARGV : $FindBin::Bin);
$tests->enter;
plan $tests->test_plan;
my $dispatcher = $tests->load_dispatcher;
$dispatcher->configure(is_psgi => 0);
foreach my File $sect (@{$tests->{files}}) {
my $dir = $tests->{cf_dir};
my $sect_name = $tests->file_title($sect);
foreach my Item $item (@{$sect->{items}}) {
SKIP: {
if ($item->{cf_PERL_MINVER} and $] < $item->{cf_PERL_MINVER}) {
Test::More::skip "by perl-$] < PERL_MINVER($item->{cf_PERL_MINVER}) $sect_name", 1;
}
if (my $action = $item->{cf_ACTION}) {
my ($method, @args) = @$action;
my $sub = $tests->can("action_$method")
or die "No such action: $method";
$sub->($tests, @args);
next;
}
my %env = (DOCUMENT_ROOT => $dir
, PATH_INFO => "/$item->{cf_FILE}"
, PATH_TRANSLATED => "$dir/$item->{cf_FILE}"
);
$item->{cf_METHOD} //= 'GET';
my $T = defined $item->{cf_TITLE} ? "[$item->{cf_TITLE}]" : '';
my $con = ostream(my $buffer);
eval {
if ($item->{cf_BREAK}) {
YATT::Lite::Breakpoint::breakpoint();
}
my $params = $item->{cf_PARAM};
if (defined $params) {
if (ref $params eq 'ARRAY'
and grep(ref $_ eq 'HASH', @$params)
or ref $params eq 'HASH'
and grep(ref $_ eq 'HASH', values %$params)) {
croak "HASH value is not allowed in PARAM block!";
}
}
$dispatcher->cf_let([noheader => 0
, lexpand($item->{cf_SITE_CONFIG})]
, runas => cgi => $con, \%env
, [$params])
};
my $header;
if ($item->{cf_ERROR}) {
like $@, qr{$item->{cf_ERROR}}
, "[$sect_name] $T ERROR $item->{cf_METHOD} $item->{cf_FILE}";
next;
} elsif (ref $@ eq 'SCALAR' and ${$@} eq 'DONE') {
# Request is completed.
} elsif (ref $@ eq 'ARRAY' and @{$@} == 3) {
# PSGI triple was raised.
$header = join("\n", @{$@->[1]});
$buffer ||= join("\n", @{$@->[2]});
} elsif ($@) {
Test::More::fail $item->{cf_FILE};
Test::More::diag $@;
next;
}
if (not $header
and $buffer =~ s/\A((?:[^\n\r]+\r?\n)*\r?\n)//) {
$header = $1;
}
if ($item->{cf_METHOD} eq 'POST' and $item->{cf_HEADER}) {
$header //= trimlast(nocr($buffer));
like $header, $tests->mkpat($item->{cf_HEADER})
, "[$sect_name] $T POST $item->{cf_FILE}";
} elsif (ref $item->{cf_BODY}) {
like nocr($buffer), $tests->mkseqpat($item->{cf_BODY})
, "[$sect_name] $T $item->{cf_METHOD} $item->{cf_FILE}";
} else {
eq_or_diff trimlast(nocr($buffer)), $item->{cf_BODY}
, "[$sect_name] $T $item->{cf_METHOD} $item->{cf_FILE}";
}
}
}
}
sub test_plan {
my MY $self = shift;
# XXX: This is overkill!
foreach my File $file (@{$self->{files}}) {
if ($file->{cf_USE_COOKIE}) {
return skip_all => "Cookie is not yet supported in offline.t";
}
}
$self->SUPER::test_plan;
}