File Coverage

blib/lib/Test/Retry.pm
Criterion Covered Total %
statement 70 73 95.8
branch 9 10 90.0
condition 5 9 55.5
subroutine 17 18 94.4
pod 1 1 100.0
total 102 111 91.8


line stmt bran cond sub pod time code
1             package Test::Retry;
2 3     3   42047 use strict;
  3         9  
  3         89  
3 3     3   17 use warnings;
  3         7  
  3         91  
4 3     3   101 use 5.008_001;
  3         9  
5 3     3   14 use Test::Builder;
  3         5  
  3         90  
6 3     3   2556 use Time::HiRes qw(sleep);
  3         4959  
  3         16  
7              
8             our $VERSION = '0.01';
9              
10             our $MAX_RETRIES = 5;
11             our $RETRY_DELAY = 0.5;
12              
13             sub import {
14 2     2   20 my ($class, %args) = @_;
15              
16 2         5 my $pkg = caller;
17 2         8 my $retry_test = _mk_retry_test($args{max}, $args{delay});
18              
19             {
20 3     3   758 no strict 'refs';
  3         6  
  3         438  
  2         4  
21 2         3 *{"$pkg\::retry_test"} = $retry_test;
  2         11  
22             }
23              
24 2 100       4 if (my @names = @{ $args{override} || [] }) {
  2 100       2269  
25 1         3 $class->_override_test_functions(
26             package => $pkg,
27             names => \@names,
28             retry_test => $retry_test,
29             );
30             }
31             }
32              
33             sub _retry_test_block {
34 4     4   12 my ($max, $delay, $block) = @_;
35              
36 4         12 my $ORIGINAL_ok = \&Test::Builder::ok;
37              
38 4         28 my $retry;
39              
40 3     3   16 no warnings 'redefine';
  3         4  
  3         1381  
41             local *Test::Builder::ok = sub {
42 12     12   3677 my ($self, $test, $name) = @_;
43              
44 12         52 $retry = 0;
45 12 50       79 $name = '' unless defined $name;
46              
47 12 100       101 if ($test) {
    100          
48 2         26 goto \&$ORIGINAL_ok; # passes
49             } elsif (--$max <= 0) {
50 2         64 $self->diag("test '$name' failing; give up");
51 2         488 goto \&$ORIGINAL_ok; # fails
52             } else {
53 8         82 $self->diag("test '$name' failing; retry ($max remaining)");
54 8         1380 $retry++;
55             }
56 4         38 };
57              
58 4         19 &$block;
59              
60 4         841 while ($retry) {
61 8         1602922 sleep $delay;
62 8         192 &$block;
63             }
64             }
65              
66             sub _mk_retry_test {
67 2     2   6 my ($max, $delay) = @_;
68              
69             return sub (&) {
70 4     4   5527 my $block = shift;
71              
72 4   66     40 _retry_test_block(
      66        
73             $max || $MAX_RETRIES,
74             $delay || $RETRY_DELAY,
75             $block,
76             );
77 2         10 };
78             }
79              
80             sub override {
81 0     0 1 0 my ($class, @names) = @_;
82 0         0 my $pkg = caller;
83              
84 0         0 $class->_override_test_functions(
85             package => $pkg,
86             names => \@names,
87             );
88             }
89              
90             sub _override_test_functions {
91 1     1   4 my ($class, %args) = @_;
92              
93 1         2 my $pkg = $args{package};
94 1         2 my @names = @{ $args{names} };
  1         2  
95 1   33     5 my $retry_test = $args{retry_test} || $pkg->can('retry_test') || _mk_retry_test();
96              
97 1         2 foreach my $name (@names) {
98 1         11 my $original_code = $pkg->can($name);
99             my $code = sub (&) {
100 1     1   13 my $block = shift;
101             $retry_test->(sub {
102 3     3   36 my @args = $block->();
103 3         82 $original_code->(@args);
104 1         9 });
105 1         4 };
106              
107 3     3   17 no strict 'refs';
  3         5  
  3         90  
108 3     3   13 no warnings 'redefine', 'prototype';
  3         9  
  3         263  
109 1         1 *{"$pkg\::$name"} = $code;
  1         1512  
110             }
111             }
112              
113             1;
114              
115             __END__