root/t/spec/fudge

Revision 20516, 6.4 kB (checked in by moritz, 8 months ago)

[fudge] add lives_ok and eval_lives_ok to fudge, bacek++

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my %OPTS;
7while( $_ = $ARGV[0], /^-/ ) {
8    shift;
9    last if /^--$/;
10    $OPTS{$_} = $_;
11}
12
13my $ME = shift;
14my $IN = shift;
15my $OUT = shift;
16
17if (!$OUT and $IN) {
18    ($OUT = $IN) =~ s/\.t$/.$ME/ or $OUT .= ".$ME";
19}
20unless ($ME and $IN and -e $IN and $OUT) {
21
22    die <<"USAGE";
23Usage: $0 [options] implname testfilename [fudgedtestfilename]
24
25    Options:
26    --keep-exit-code
27        by default, fudge modifies the exit code for fudged test files to 1.
28        supplying this option will suppress that behavior.
29
30    Verbs:
31    #?implname [num] skip 'reason'
32        comment out num tests or blocks and call skip(num)
33
34    #?implname [num] eval 'reason'
35        eval num tests or blocks and skip(num) on parsefail
36
37    #?implname [num] try 'reason'
38        try num tests or blocks and fail on exception
39
40    #?implname [num] todo 'reason', :by<1.2.3>
41        run num tests or blocks with todo() preset
42
43    #?implname emit your_ad_here();
44        just pass through your_ad_here();
45
46    #?DOES count
47        for all implementations, the following thing does count tests
48        (disables any attempt to autocount tests within the construct)
49        when construct is a sub, registers the sub name as tester
50        (and multiplies calls to tester sub by count tests)
51
52    where
53    implname is the lc name of your implementation, e.g. pugs or rakudo
54    num is the number of statements or blocks to preprocess, defaults to 1
55    count is how many tests the following construct counts as
56
57
58USAGE
59}
60
61if (-e $OUT) {
62    if (-M $IN >= -M $OUT and -M $0 >= -M $OUT) {
63        print "$OUT\n";     # unchanged, so no need to refudge
64        exit(0);
65    }
66    else {
67        unlink $OUT;        # old fudged version, may or may not regenerate...
68    }
69}
70
71my $REALLY_FUDGED = 0;
72my $OUTPUT = "";
73my $FUDGE = "";
74our $PENDING = 0;
75my $ARGS = '';
76my $IS = '\\b(?:is|ok|nok|is_deeply|is_approx|isnt|like|unlike|eval_dies_ok|cmp_ok|isa_ok|use_ok|throws_ok|dies_ok|lives_ok|eval_lives_ok|pass|flunk)(?:\\b|_)';
77my %DOES;
78my $DOES = 0;
79my $EXIT = $OPTS{'--keep-exit-code'} ? '' : 'exit(1);';
80
81@ARGV = ($IN);
82fudgeblock();
83
84if ($REALLY_FUDGED) {
85    open OUT, ">", $OUT or die "Can't create $OUT: $!";
86    print OUT $OUTPUT;
87    print OUT <<"END";
88
89say "# FUDGED!";
90$EXIT
91END
92    close OUT;
93    print "$OUT\n"; # pick the output file to run
94}
95else {
96    print "$IN\n";  # pick the input file to run
97}
98
99sub fudgeblock {
100    while (<>) {
101        if (/^\s*\#\?DOES[:\s] \s* (.*)/x) {
102            $DOES = $1;
103            next;
104        }
105        if (/^\s*\#\? (\w+)[:\s] \s* (.*)/x and $1 eq $ME) {
106            $REALLY_FUDGED = 1;
107            $ARGS = $2;
108            if ($ARGS =~ s/^emit\s*//) {
109                $_ = $ARGS;
110                next;
111            }
112            if ($ARGS =~ s/^(\d+)\s*//) {
113                $PENDING = $1;
114            }
115            else {
116                $PENDING = 1;
117            }
118            $ARGS =~ s/^(\w+)\s*//;
119            $FUDGE = $1;
120        }
121
122        next if /^\s*#/;
123        next if /^\s*$/;
124
125        if ($DOES) {
126            if (/^\s*(sub|multi|proto)\b/) {
127                my $tmp = $_;
128                $tmp =~ s/^\s*proto\s+//;
129                $tmp =~ s/^\s*multi\s+//;
130                $tmp =~ s/^\s*sub\s+//;
131                $tmp =~ /^(\w+)/;
132                $DOES{$1} = $DOES;
133                $DOES = 0;
134                next;
135            }
136        }
137
138        next unless $PENDING > 0;
139
140        if (/^\{/) {
141            $PENDING--;
142            if ($FUDGE eq 'todo') {
143                local $PENDING = 999999;    # do all in block as one action
144                $OUTPUT .= $_;
145                $DOES = 0;  # XXX ignore?
146                fudgeblock();
147                $_ = '';
148            }
149            else {
150                my $more;
151                while (defined($more = <>)) {
152                    $_ .= $more;
153                    last if $more =~ /^\}/;
154                }
155                my $numtests = $DOES || do {
156                    my $tmp = $_;
157                    my $nt = 0;
158                    $nt += $1 while $tmp =~ s/^#\?DOES[:\s]\s*(\d+).*\n.*\n//m;
159                    if (%DOES) {
160                            my $does = join('|',keys(%DOES));
161                            $nt += $DOES{$1} while $tmp =~ s/^\s*($does)\b//mx;
162                    }
163                    $nt += () = $tmp =~ m/^(\s*$IS)/mgx;
164                    $nt;
165                };
166                if ($FUDGE eq 'skip') {
167                    s/^/# /mg;
168                    $_ = "skip($numtests, $ARGS);" . $_;
169                }
170                elsif ($FUDGE eq 'try') {
171                    chomp;
172                    $_ = "(try $_) // flunk($ARGS);\n";
173                }
174                elsif ($FUDGE eq 'eval') {
175                    chomp;
176                    s/(['\\])/\\$1/g;
177                    $_ = "eval('$_') // skip($numtests, $ARGS);\n";
178                }
179                else {
180                    warn "Don't know how to mark block for $FUDGE!\n";
181                }
182            }
183        }
184        else {
185            if ($FUDGE eq 'todo') {
186                $DOES = 0;  # XXX ignore?
187                $PENDING -= s/^(\s*)/${1}todo($ARGS); / if /^\s*$IS/;
188            }
189            else {
190                while ($_ !~ /;[ \t]*(#.*)?$/) {
191                    my $more = <>;
192                    last unless $more;
193                    $_ .= $more;
194                }
195                my ($keyword) = /^\s*(\w+)/ || '';
196                my $numtests;
197                if ($DOES{$keyword}) {
198                    $numtests = $DOES{$keyword};
199                }
200                elsif ($DOES) {
201                    $numtests = $DOES;
202                }
203                else {
204                    next unless /^\s*$IS/;
205                    $numtests = 1;
206                }
207                $PENDING--;
208                $_ = "{ " . $_ . " }";
209                if ($FUDGE eq 'skip') {
210                    s/^/# /mg;
211                    $_ = "skip($numtests,$ARGS); $_\n";
212                }
213                elsif ($FUDGE eq 'try') {
214                    $_ = "(try $_) // flunk($ARGS);\n";
215                }
216                elsif ($FUDGE eq 'eval') {
217                    s/(['\\])/\\$1/g;
218                    $_ = "eval('$_') // skip($numtests,$ARGS);\n";
219                }
220                else {
221                    warn "Don't know how to mark statement for $FUDGE!\n";
222                }
223            }
224        }
225    }
226    continue {
227        $OUTPUT .= $_;
228        return if /^\}/ and $PENDING > 0;
229    }
230}
Note: See TracBrowser for help on using the browser.