File Coverage

blib/lib/Test/Stream.pm
Criterion Covered Total %
statement 117 119 98.3
branch 49 56 87.5
condition 14 17 82.3
subroutine 14 14 100.0
pod 0 5 0.0
total 194 211 91.9


line stmt bran cond sub pod time code
1             package Test::Stream;
2 102     102   58010 use strict;
  102         179  
  102         2741  
3 102     102   498 use warnings;
  102         166  
  102         3090  
4 102     102   485 use vars qw/$VERSION/;
  102         154  
  102         6759  
5              
6             $Test::Stream::VERSION = '1.302026';
7             $VERSION = eval $VERSION;
8              
9 102     102   496 use Carp qw/croak/;
  102         160  
  102         6723  
10 102     102   537 use Scalar::Util qw/reftype/;
  102         176  
  102         9570  
11              
12 102     102   55657 use Test::Stream::Sync;
  102         284  
  102         3472  
13              
14 102     102   603 use Test::Stream::Util qw/try pkg_to_file/;
  102         196  
  102         716  
15              
16             sub default {
17 1     1 0 174 croak "No plugins or bundles specified (Maybe try '-Classic'?)"
18             }
19              
20             sub import {
21 121     121   1510 my $class = shift;
22 121         477 my @caller = caller;
23              
24 121 100       536 push @_ => $class->default unless @_;
25              
26 120         456 $class->load(\@caller, @_);
27              
28 118         127499 1;
29             }
30              
31             sub load {
32 156     156 0 306 my $class = shift;
33 156         274 my $caller = shift;
34              
35 156         253 my @order;
36             my %args;
37 0         0 my %skip;
38              
39 156         671 while (my $arg = shift @_) {
40 1745   100     7332 my $type = reftype($arg) || "";
41              
42 1745 100       3609 if ($type eq 'CODE') {
43 113         258 push @order => $arg;
44 113         396 next;
45             }
46              
47             # Strip off the '+', which may be combined with ':' or '-' at the
48             # start.
49 1632 100       3752 my $full = ($arg =~ s/^([!:-]?)\+/$1/) ? 1 : 0;
50              
51             # Disallowed plugin
52 1632 100       4139 if ($arg =~ m/^!(.*)$/) {
53 3 100       10 my $pkg = $full ? $1 : "Test::Stream::Plugin::$1";
54 3         7 $skip{$pkg}++;
55 3         9 next;
56             }
57              
58             # Bundle
59 1629 100       3775 if ($arg =~ m/^-(.*)$/) {
60 162 100       715 my $pkg = $full ? $1 : "Test::Stream::Bundle::$1";
61 162         641 my $file = pkg_to_file($pkg);
62 162         85267 require $file;
63 162         1172 unshift @_ => $pkg->plugins;
64 162         855 next;
65             }
66              
67             # Local Bundle
68 1467 100       3088 if ($arg =~ m/^:(.*)$/) {
69 2 50       9 my $pkg = $full ? $1 : "Test::Stream::Bundle::$1";
70 2         17 my $file = pkg_to_file($pkg);
71              
72             local @INC = (
73             ($ENV{TS_LB_PATH} ? split(':', $ENV{TS_LB_PATH}) : ()),
74             't/lib',
75             'lib',
76             sub {
77 1     1   3 my ($me, $fname) = @_;
78 1 50       5 return unless $fname eq $file;
79 1         18 die "Could not load LOCAL PROJECT bundle '$pkg' (Do you need to set TS_LB_PATH?)\n";
80             },
81 2 50       89 @INC,
82             );
83              
84 2         520 require $file;
85 1         11 unshift @_ => $pkg->plugins;
86 1         12 next;
87             }
88              
89 1465 100       3696 if ($arg =~ m/^[a-z]/) {
90 7         16 my $method = "opt_$arg";
91              
92 7 100       91 die "'$arg' is not a valid option for '$class' (Did you intend to use the '" . ucfirst($arg) . "' plugin?) at $caller->[1] line $caller->[2].\n"
93             unless $class->can($method);
94              
95 6         155 $class->$method(list => \@_, order => \@order, args => \%args, skip => \%skip);
96 6         34 next;
97             }
98              
99             # Load the plugin
100 1458 100       4353 $arg = 'Test::Stream::Plugin::' . $arg unless $full;
101              
102             # Get the value
103 1458         2000 my $val;
104              
105             # Arg is specified
106 1458 100 66     9264 $val = shift @_ if @_ && (ref($_[0]) || ($_[0] && $_[0] eq '*'));
      66        
107              
108             # Special Cases
109 1458 50 100     3948 $val = $val eq '*' ? ['-all'] : [$val]
    100          
110             if defined($val) && !ref($val);
111              
112             # Make sure we only list it in @order once.
113 1458 100       3936 push @order => $arg unless $args{$arg};
114              
115             # Override any existing value, last wins.
116 1458 100       5619 $args{$arg} = $val if defined $val;
117             }
118              
119 154         365 for my $arg (@order) {
120 1567   100     8828 my $type = reftype($arg) || "";
121 1567 100       7383 if ($type eq 'CODE') {
122 113         490 $arg->($caller);
123 113         372 next;
124             }
125              
126 1454 100       3661 next if $skip{$arg};
127              
128 1450         2615 my $import = $args{$arg};
129 1450         2023 my $mod = $arg;
130              
131 1450         4707 my $file = pkg_to_file($mod);
132 1450 100       2616 unless (eval { require $file; 1 }) {
  1450         691025  
  1448         6125  
133 2   50     7 my $error = $@ || 'unknown error';
134 2         5 my $file = __FILE__;
135 2         3 my $line = __LINE__ - 3;
136 2         39 $error =~ s/ at \Q$file\E line $line.*//;
137 2         286 croak "Could not load Test::Stream plugin '$arg': $error";
138             }
139              
140 1448 100       16775 if ($mod->can('load_ts_plugin')) {
    50          
    0          
141 542         2434 $mod->load_ts_plugin($caller, @$import);
142             }
143             elsif (my $meta = Test::Stream::Exporter::Meta->get($mod)) {
144 906         3081 Test::Stream::Exporter::export_from($mod, $caller->[0], $import);
145             }
146             elsif (@$import) {
147 0         0 croak "Module '$mod' does it implement 'load_ts_plugin()', nor does it export using Test::Stream::Exporter."
148             }
149             }
150              
151 139         954 Test::Stream::Sync->loaded(1);
152             }
153              
154             sub opt_class {
155 5     5 0 23 shift;
156 5         19 my %params = @_;
157 5         9 my $list = $params{list};
158 5         9 my $args = $params{args};
159 5         8 my $order = $params{order};
160              
161 5         10 my $class = shift @$list;
162              
163 3         8 push @{$params{order}} => 'Test::Stream::Plugin::Class'
164 5 100       17 unless $args->{'Test::Stream::Plugin::Class'};
165              
166 5         20 $args->{'Test::Stream::Plugin::Class'} = [$class];
167             }
168              
169             sub opt_skip_without {
170 4     4 0 21 shift;
171 4         18 my %params = @_;
172 4         8 my $list = $params{list};
173 4         7 my $args = $params{args};
174 4         7 my $order = $params{order};
175              
176 4         6 my $class = shift @$list;
177              
178 3         8 push @{$params{order}} => 'Test::Stream::Plugin::SkipWithout'
179 4 100       13 unless $args->{'Test::Stream::Plugin::SkipWithout'};
180              
181 4   100     22 $args->{'Test::Stream::Plugin::SkipWithout'} ||= [];
182 4         6 push @{$args->{'Test::Stream::Plugin::SkipWithout'}} => $class;
  4         16  
183             }
184              
185             sub opt_srand {
186 2     2 0 19 shift;
187 2         7 my %params = @_;
188 2         4 my $list = $params{list};
189 2         4 my $args = $params{args};
190 2         3 my $order = $params{order};
191              
192 2         5 my $seed = shift @$list;
193              
194 1         2 push @{$params{order}} => 'Test::Stream::Plugin::SRand'
195 2 100       7 unless $args->{'Test::Stream::Plugin::SRand'};
196              
197 2         15 $args->{'Test::Stream::Plugin::SRand'} = [$seed];
198             }
199              
200             1;
201              
202             __END__