Perl-Critic-Policy-Troglodyne-ProhibitPipeOpen.t 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. use strict;
  2. use warnings;
  3. use Test::More;
  4. use FindBin;
  5. # policy/ has to be on @INC *before* Perl::Critic loads: it finds policies by
  6. # scanning @INC once, at load time, so adding the directory afterwards leaves
  7. # it unable to see ours.
  8. use lib "$FindBin::Bin/../policy";
  9. # The policy is a development tool, not part of tCMS proper -- it lives in
  10. # policy/ and is never installed. Anyone without Perl::Critic can still run
  11. # the rest of the suite.
  12. BEGIN {
  13. plan skip_all => 'Perl::Critic not installed' unless eval { require Perl::Critic; 1 };
  14. }
  15. my $policy = 'Troglodyne::ProhibitPipeOpen';
  16. require_ok("Perl::Critic::Policy::$policy") or BAIL_OUT("Can't find SUT");
  17. # -profile => '' so the repo's own .perlcriticrc, which perlcritic would
  18. # otherwise find by walking up from cwd, doesn't drag in every other policy and
  19. # fail these snippets for want of POD.
  20. # Note the hyphen: -single_policy is silently ignored and you get all 222
  21. # policies instead. -profile => '' so the repo's own .perlcriticrc, which
  22. # perlcritic would otherwise find by walking up from cwd, doesn't drag in every
  23. # other policy and fail these snippets for want of POD.
  24. my $critic = Perl::Critic->new( -profile => q{}, '-single-policy' => $policy, -severity => 1 );
  25. sub violations {
  26. my ($source) = @_;
  27. return scalar $critic->critique( \"use strict;\nuse warnings;\n$source\n" );
  28. }
  29. subtest 'opens that spawn something are caught' => sub {
  30. my %cases = (
  31. 'three-arg read' => q{open( my $fh, '-|', 'ls', '-l' );},
  32. 'three-arg write' => q{open( my $fh, '|-', 'mail', $to );},
  33. 'bare two-arg fork' => q{open( my $fh, '-|' );},
  34. 'two-arg trailing' => q{open( FH, 'ls -l |' );},
  35. 'two-arg leading' => q{open( FH, '| mail bob' );},
  36. 'qw-quoted mode' => q{open( my $fh, q{-|}, 'ls' );},
  37. );
  38. foreach my $name ( sort keys %cases ) {
  39. is( violations( $cases{$name} ), 1, "$name is a violation" );
  40. }
  41. };
  42. subtest 'ordinary file opens are left alone' => sub {
  43. my %cases = (
  44. 'read' => q{open( my $fh, '<', $path );},
  45. 'write' => q{open( my $fh, '>', $path );},
  46. 'append' => q{open( my $fh, '>>', $path );},
  47. 'interpolated path' => q{open( my $fh, '>', "$dir/thing" );},
  48. 'in-memory' => q{open( my $fh, '<', \$scalar );},
  49. 'opendir' => q{opendir( my $dh, $dir );},
  50. 'bitwise or' => q{my $x = $a | $b;},
  51. 'a sub named open' => q{$obj->open( '-|', 'ls' );},
  52. );
  53. foreach my $name ( sort keys %cases ) {
  54. is( violations( $cases{$name} ), 0, "$name is not a violation" );
  55. }
  56. };
  57. subtest 'the annotation is what signs it off' => sub {
  58. is(
  59. violations(q{open( my $fh, '-|', 'ls' ); ## no critic (Troglodyne::ProhibitPipeOpen)}),
  60. 0,
  61. 'an explicit no-critic suppresses it'
  62. );
  63. };
  64. done_testing();