Blame t/lib/Cases.pm

Packit Service 44c065
package Cases;
Packit Service 44c065
use strict;
Packit Service 44c065
use warnings;
Packit Service 44c065
use Test::More;
Packit Service 44c065
use Capture::Tiny ':all';
Packit Service 44c065
Packit Service 44c065
require Exporter;
Packit Service 44c065
our @ISA = 'Exporter';
Packit Service 44c065
our @EXPORT_OK = qw(
Packit Service 44c065
  run_test
Packit Service 44c065
);
Packit Service 44c065
Packit Service 44c065
my $locale_ok = eval {
Packit Service 44c065
    my $err = capture_stderr { system($^X, '-we', 1) };
Packit Service 44c065
    $err !~ /setting locale failed/i;
Packit Service 44c065
};
Packit Service 44c065
Packit Service 44c065
my $have_diff = eval {
Packit Service 44c065
  require Test::Differences;
Packit Service 44c065
  Test::Differences->import;
Packit Service 44c065
  $Test::Differences::VERSION < 0.60; # 0.60+ is causing strange failures
Packit Service 44c065
};
Packit Service 44c065
Packit Service 44c065
sub _is_or_diff {
Packit Service 44c065
  my ($g,$e,$l) = @_;
Packit Service 44c065
  if ( $have_diff ) { eq_or_diff( $g, $e, $l ); }
Packit Service 44c065
  else { is( $g, $e, $l ); }
Packit Service 44c065
}
Packit Service 44c065
Packit Service 44c065
sub _binmode {
Packit Service 44c065
  my $text = shift;
Packit Service 44c065
  return $text eq 'unicode' ? 'binmode(STDOUT,q{:utf8}); binmode(STDERR,q{:utf8});' : '';
Packit Service 44c065
}
Packit Service 44c065
Packit Service 44c065
sub _set_utf8 {
Packit Service 44c065
  my $t = shift;
Packit Service 44c065
  return unless $t eq 'unicode';
Packit Service 44c065
  my %seen;
Packit Service 44c065
  my @orig_layers = (
Packit Service 44c065
    [ grep {$_ ne 'unix' and $_ ne 'perlio' and $seen{stdout}{$_}++} PerlIO::get_layers(\*STDOUT) ],
Packit Service 44c065
    [ grep {$_ ne 'unix' and $_ ne 'perlio' and $seen{stderr}{$_}++} PerlIO::get_layers(\*STDERR) ],
Packit Service 44c065
  );
Packit Service 44c065
  binmode(STDOUT, ":utf8") if fileno(STDOUT);
Packit Service 44c065
  binmode(STDERR, ":utf8") if fileno(STDERR);
Packit Service 44c065
  return @orig_layers;
Packit Service 44c065
}
Packit Service 44c065
Packit Service 44c065
sub _restore_layers {
Packit Service 44c065
  my ($t, @orig_layers) = @_;
Packit Service 44c065
  return unless $t eq 'unicode';
Packit Service 44c065
  binmode(STDOUT, join( ":", "", "raw", @{$orig_layers[0]})) if fileno(STDOUT);
Packit Service 44c065
  binmode(STDERR, join( ":", "", "raw", @{$orig_layers[1]})) if fileno(STDERR);
Packit Service 44c065
}
Packit Service 44c065
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
Packit Service 44c065
my %texts = (
Packit Service 44c065
  short => 'Hello World',
Packit Service 44c065
  multiline => 'First line\nSecond line\n',
Packit Service 44c065
  ( $] lt "5.008" ? () : ( unicode => 'Hi! \x{263a}\n') ),
Packit Service 44c065
);
Packit Service 44c065
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
#  fcn($perl_code_string) => execute the perl in current process or subprocess
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
Packit Service 44c065
my %methods = (
Packit Service 44c065
  perl    => sub { eval $_[0] },
Packit Service 44c065
  sys  => sub { system($^X, '-e', $_[0]) },
Packit Service 44c065
);
Packit Service 44c065
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
Packit Service 44c065
my %channels = (
Packit Service 44c065
  stdout  => {
Packit Service 44c065
    output => sub { _binmode($_[0]) . "print STDOUT qq{STDOUT:$texts{$_[0]}}" },
Packit Service 44c065
    expect => sub { eval "qq{STDOUT:$texts{$_[0]}}", "" },
Packit Service 44c065
  },
Packit Service 44c065
  stderr  => {
Packit Service 44c065
    output => sub { _binmode($_[0]) . "print STDERR qq{STDERR:$texts{$_[0]}}" },
Packit Service 44c065
    expect => sub { "", eval "qq{STDERR:$texts{$_[0]}}" },
Packit Service 44c065
  },
Packit Service 44c065
  both    => {
Packit Service 44c065
    output => sub { _binmode($_[0]) . "print STDOUT qq{STDOUT:$texts{$_[0]}}; print STDERR qq{STDERR:$texts{$_[0]}}" },
Packit Service 44c065
    expect => sub { eval "qq{STDOUT:$texts{$_[0]}}", eval "qq{STDERR:$texts{$_[0]}}" },
Packit Service 44c065
  },
Packit Service 44c065
  empty   => {
Packit Service 44c065
    output => sub { _binmode($_[0]) . "print STDOUT qq{}; print STDERR qq{}" },
Packit Service 44c065
    expect => sub { "", "" },
Packit Service 44c065
  },
Packit Service 44c065
  nooutput=> {
Packit Service 44c065
    output => sub { _binmode($_[0]) },
Packit Service 44c065
    expect => sub { "", "" },
Packit Service 44c065
  },
Packit Service 44c065
);
Packit Service 44c065
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
Packit Service 44c065
my %tests = (
Packit Service 44c065
  capture => {
Packit Service 44c065
    cnt   => 2,
Packit Service 44c065
    test  => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($got_out, $got_err) = capture {
Packit Service 44c065
        $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $got_out, $expected[0], "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
      _is_or_diff( $got_err, $expected[1], "$l|$m|$c|$t - got STDERR" );
Packit Service 44c065
    },
Packit Service 44c065
  },
Packit Service 44c065
  capture_scalar => {
Packit Service 44c065
    cnt   => 1,
Packit Service 44c065
    test  => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my $got_out = capture {
Packit Service 44c065
        $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $got_out, $expected[0], "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
    },
Packit Service 44c065
  },
Packit Service 44c065
  capture_stdout => {
Packit Service 44c065
    cnt   => 3,
Packit Service 44c065
    test  => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($inner_out, $inner_err);
Packit Service 44c065
      my ($outer_out, $outer_err) = capture {
Packit Service 44c065
        $inner_out = capture_stdout {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $inner_out, $expected[0], "$l|$m|$c|$t - inner STDOUT" );
Packit Service 44c065
      _is_or_diff( $outer_out, "",           "$l|$m|$c|$t - outer STDOUT" );
Packit Service 44c065
      _is_or_diff( $outer_err, $expected[1], "$l|$m|$c|$t - outer STDERR" );
Packit Service 44c065
    },
Packit Service 44c065
  },
Packit Service 44c065
  capture_stderr => {
Packit Service 44c065
    cnt   => 3,
Packit Service 44c065
    test  => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($inner_out, $inner_err);
Packit Service 44c065
      my ($outer_out, $outer_err) = capture {
Packit Service 44c065
        $inner_err = capture_stderr {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $inner_err, $expected[1], "$l|$m|$c|$t - inner STDERR" );
Packit Service 44c065
      _is_or_diff( $outer_out, $expected[0], "$l|$m|$c|$t - outer STDOUT" );
Packit Service 44c065
      _is_or_diff( $outer_err, "",           "$l|$m|$c|$t - outer STDERR" );
Packit Service 44c065
    },
Packit Service 44c065
  },
Packit Service 44c065
  capture_merged => {
Packit Service 44c065
    cnt   => 2,
Packit Service 44c065
    test  => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my $got_out = capture_merged {
Packit Service 44c065
        $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      like( $got_out, qr/\Q$expected[0]\E/, "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
      like( $got_out, qr/\Q$expected[1]\E/, "$l|$m|$c|$t - got STDERR" );
Packit Service 44c065
    },
Packit Service 44c065
  },
Packit Service 44c065
  tee => {
Packit Service 44c065
    cnt => 4,
Packit Service 44c065
    test => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($got_out, $got_err);
Packit Service 44c065
      my ($tee_out, $tee_err) = capture {
Packit Service 44c065
        ($got_out, $got_err) = tee {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $got_out, $expected[0], "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_out, $expected[0], "$l|$m|$c|$t - tee STDOUT" );
Packit Service 44c065
      _is_or_diff( $got_err, $expected[1], "$l|$m|$c|$t - got STDERR" );
Packit Service 44c065
      _is_or_diff( $tee_err, $expected[1], "$l|$m|$c|$t - tee STDERR" );
Packit Service 44c065
    }
Packit Service 44c065
  },
Packit Service 44c065
  tee_scalar => {
Packit Service 44c065
    cnt => 3,
Packit Service 44c065
    test => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($got_out, $got_err);
Packit Service 44c065
      my ($tee_out, $tee_err) = capture {
Packit Service 44c065
        $got_out = tee {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $got_out, $expected[0], "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_out, $expected[0], "$l|$m|$c|$t - tee STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_err, $expected[1], "$l|$m|$c|$t - tee STDERR" );
Packit Service 44c065
    }
Packit Service 44c065
  },
Packit Service 44c065
  tee_stdout => {
Packit Service 44c065
    cnt => 3,
Packit Service 44c065
    test => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($inner_out, $inner_err);
Packit Service 44c065
      my ($tee_out, $tee_err) = capture {
Packit Service 44c065
        $inner_out = tee_stdout {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $inner_out, $expected[0], "$l|$m|$c|$t - inner STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_out, $expected[0], "$l|$m|$c|$t - teed STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_err, $expected[1], "$l|$m|$c|$t - unmodified STDERR" );
Packit Service 44c065
    }
Packit Service 44c065
  },
Packit Service 44c065
  tee_stderr => {
Packit Service 44c065
    cnt => 3,
Packit Service 44c065
    test => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($inner_out, $inner_err);
Packit Service 44c065
      my ($tee_out, $tee_err) = capture {
Packit Service 44c065
        $inner_err = tee_stderr {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      _is_or_diff( $inner_err, $expected[1], "$l|$m|$c|$t - inner STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_out, $expected[0], "$l|$m|$c|$t - unmodified STDOUT" );
Packit Service 44c065
      _is_or_diff( $tee_err, $expected[1], "$l|$m|$c|$t - teed STDERR" );
Packit Service 44c065
    }
Packit Service 44c065
  },
Packit Service 44c065
  tee_merged => {
Packit Service 44c065
    cnt => 5,
Packit Service 44c065
    test => sub {
Packit Service 44c065
      my ($m, $c, $t, $l) = @_;
Packit Service 44c065
      my ($got_out, $got_err);
Packit Service 44c065
      my ($tee_out, $tee_err) = capture {
Packit Service 44c065
        $got_out = tee_merged {
Packit Service 44c065
          $methods{$m}->( $channels{$c}{output}->($t) );
Packit Service 44c065
        };
Packit Service 44c065
      };
Packit Service 44c065
      my @expected = $channels{$c}{expect}->($t);
Packit Service 44c065
      like( $got_out, qr/\Q$expected[0]\E/, "$l|$m|$c|$t - got STDOUT" );
Packit Service 44c065
      like( $got_out, qr/\Q$expected[1]\E/, "$l|$m|$c|$t - got STDERR" );
Packit Service 44c065
      like( $tee_out, qr/\Q$expected[0]\E/, "$l|$m|$c|$t - tee STDOUT (STDOUT)" );
Packit Service 44c065
      like( $tee_out, qr/\Q$expected[1]\E/, "$l|$m|$c|$t - tee STDOUT (STDERR)" );
Packit Service 44c065
      _is_or_diff( $tee_err, '', "$l|$m|$c|$t - tee STDERR" );
Packit Service 44c065
    }
Packit Service 44c065
  },
Packit Service 44c065
);
Packit Service 44c065
Packit Service 44c065
#--------------------------------------------------------------------------#
Packit Service 44c065
# What I want to be able to do:
Packit Service 44c065
#
Packit Service 44c065
# test_it(
Packit Service 44c065
#   input => 'short',
Packit Service 44c065
#   channels => 'both',
Packit Service 44c065
#   method => 'perl'
Packit Service 44c065
# )
Packit Service 44c065
Packit Service 44c065
sub run_test {
Packit Service 44c065
  my $test_type = shift or return;
Packit Service 44c065
  my $todo = shift || '';
Packit Service 44c065
  my $skip_utf8 = shift || '';
Packit Service 44c065
  local $ENV{PERL_CAPTURE_TINY_TIMEOUT} = 0; # don't timeout during testing
Packit Service 44c065
  for my $m ( keys %methods ) {
Packit Service 44c065
    if ( ($m eq 'sys' || substr($test_type,0,3) eq 'tee' ) && ! $locale_ok ) {
Packit Service 44c065
        SKIP: {
Packit Service 44c065
            skip "Perl could not initialize locale", 1
Packit Service 44c065
        };
Packit Service 44c065
        next;
Packit Service 44c065
    }
Packit Service 44c065
    for my $c ( keys %channels ) {
Packit Service 44c065
      for my $t ( keys %texts     ) {
Packit Service 44c065
        next if $t eq 'unicode' && $skip_utf8;
Packit Service 44c065
        my @orig_layers = _set_utf8($t);
Packit Service 44c065
        local $TODO = "not supported on all platforms"
Packit Service 44c065
          if $t eq $todo;
Packit Service 44c065
        $tests{$test_type}{test}->($m, $c, $t, $test_type);
Packit Service 44c065
        _restore_layers($t, @orig_layers);
Packit Service 44c065
      }
Packit Service 44c065
    }
Packit Service 44c065
  }
Packit Service 44c065
}
Packit Service 44c065
Packit Service 44c065
1;