File Coverage

blib/lib/Test/Stream/Compare.pm
Criterion Covered Total %
statement 92 94 97.8
branch 44 50 88.0
condition 20 26 76.9
subroutine 28 28 100.0
pod 8 12 66.6
total 192 210 91.4


line stmt bran cond sub pod time code
1             package Test::Stream::Compare;
2 100     100   1005 use strict;
  100         176  
  100         2637  
3 100     100   503 use warnings;
  100         184  
  100         2826  
4              
5 100     100   504 use Test::Stream::Util qw/try sub_info/;
  100         179  
  100         683  
6 100     100   55874 use Test::Stream::Delta;
  100         273  
  100         3250  
7              
8 100     100   607 use Carp qw/confess croak/;
  100         174  
  100         5412  
9 100     100   509 use Scalar::Util qw/blessed/;
  100         192  
  100         4081  
10              
11 100     100   524 use Test::Stream::Exporter;
  100         190  
  100         697  
12             export compare => sub {
13 1895     1895   3509 my ($got, $check, $convert) = @_;
14              
15 1895         5224 $check = $convert->($check);
16              
17 1895         7020 return $check->run(
18             id => undef,
19             got => $got,
20             exists => 1,
21             convert => $convert,
22             seen => {},
23             );
24             };
25              
26             sub MAX_CYCLES() { 75 }
27              
28             my @BUILD;
29              
30 1999 100   1999   9195 export get_build => sub { @BUILD ? $BUILD[-1] : undef };
31 1     1   5 export push_build => sub { push @BUILD => $_[0] };
32              
33             export pop_build => sub {
34 4 100 66 4   69 return pop @BUILD if @BUILD && $_[0] && $BUILD[-1] == $_[0];
      100        
35 3 100       24 my $have = @BUILD ? "$BUILD[-1]" : 'undef';
36 3 100       13 my $want = $_[0] ? "$_[0]" : 'undef';
37 3         511 croak "INTERNAL ERROR: Attempted to pop incorrect build, have $have, tried to pop $want";
38             };
39              
40             export build => sub {
41 456     456   827 my ($class, $code) = @_;
42              
43 456         3536 my @caller = caller(1);
44              
45 456 100       1377 die "'$caller[3]\()' should not be called in void context in $caller[1] line $caller[2]\n"
46             unless defined(wantarray);
47              
48 455         2394 my $build = $class->new(builder => $code, called => \@caller);
49              
50 455         793 push @BUILD => $build;
51 455     455   2334 my ($ok, $err) = try { $code->($build); 1 };
  455         1240  
  440         1317  
52 455         1673 pop @BUILD;
53 455 100       1241 die $err unless $ok;
54              
55 440         1779 return $build;
56             };
57 100     100   586 no Test::Stream::Exporter;
  100         209  
  100         497  
58              
59             use Test::Stream::HashBase(
60 100         615 accessors => [qw/builder _file _lines _info called/]
61 100     100   531 );
  100         181  
62              
63             *set_lines = \&set__lines;
64             *set_file = \&set__file;
65              
66             sub init {
67 9933     9933 0 13768 my $self = shift;
68 9933 100       24505 $self->{_lines} = delete $self->{lines} if exists $self->{lines};
69 9933 100       34942 $self->{_file} = delete $self->{file} if exists $self->{file};
70             }
71              
72             sub file {
73 64     64 0 98 my $self = shift;
74 64 100       207 return $self->{+_FILE} if $self->{+_FILE};
75              
76 50 100       151 if ($self->{+BUILDER}) {
    50          
77 32   33     80 $self->{+_INFO} ||= sub_info($self->{+BUILDER});
78 32         130 return $self->{+_INFO}->{file};
79             }
80             elsif ($self->{+CALLED}) {
81 0         0 return $self->{+CALLED}->[1];
82             }
83              
84 18         127 return undef;
85             }
86              
87             sub lines {
88 228     228 0 377 my $self = shift;
89 228 100       789 return $self->{+_LINES} if $self->{+_LINES};
90              
91 133 100       322 if ($self->{+BUILDER}) {
92 75   66     252 $self->{+_INFO} ||= sub_info($self->{+BUILDER});
93 75 50       100 return $self->{+_INFO}->{lines} if @{$self->{+_INFO}->{lines}};
  75         467  
94             }
95 58 50       134 if ($self->{+CALLED}) {
96 0         0 return [$self->{+CALLED}->[2]];
97             }
98 58         208 return [];
99             }
100              
101 100     100   603 use Test::Stream::Delta;
  100         193  
  100         37293  
102 230     230 1 1275 sub delta_class { 'Test::Stream::Delta' }
103              
104 5256     5256 1 9277 sub deltas { () }
105 139     139 1 334 sub got_lines { () }
106              
107 74     74 0 280 sub stringify_got { 0 }
108              
109 50     50 1 139 sub operator { '' }
110 1     1 1 210 sub verify { confess "unimplemented" }
111 1     1 1 167 sub name { confess "unimplemented" }
112              
113             sub render {
114 152     152 1 206 my $self = shift;
115 152         462 return $self->name;
116             }
117              
118             sub run {
119 7379     7379 1 10170 my $self = shift;
120 7379         27468 my %params = @_;
121              
122 7379         11691 my $id = $params{id};
123 7379 50       17038 my $convert = $params{convert} or confess "no convert sub provided";
124 7379   50     17183 my $seen = $params{seen} ||= {};
125              
126             $params{exists} = exists $params{got} ? 1 : 0
127 7379 50       16095 unless exists $params{exists};
    100          
128              
129 7379         10072 my $exists = $params{exists};
130 7379 100       15466 my $got = $exists ? $params{got} : undef;
131              
132             # Prevent infinite cycles
133 7379 100 100     30279 if ($got && ref $got) {
134             die "Cycle detected in comparison, aborting"
135 2164 50 66     7280 if $seen->{$got} && $seen->{$got} >= MAX_CYCLES;
136 2164         6272 $seen->{$got}++;
137             }
138              
139 7379         30441 my $ok = $self->verify(%params);
140 7379 100       33390 my @deltas = $ok ? $self->deltas(%params) : ();
141              
142 7379 100 100     34475 $seen->{$got}-- if $got && ref $got;
143              
144 7379 100 100     65570 return if $ok && !@deltas;
145              
146 215 100       645 return $self->delta_class->new(
147             verified => $ok,
148             id => $id,
149             got => $got,
150             check => $self,
151             children => \@deltas,
152             $exists ? () : (dne => 'got'),
153             );
154             }
155              
156             1;
157              
158             __END__