File Coverage

blib/lib/Outhentic.pm
Criterion Covered Total %
statement 18 208 8.6
branch 0 112 0.0
condition n/a
subroutine 6 16 37.5
pod n/a
total 24 336 7.1


line stmt bran cond sub pod time code
1             package Outhentic;
2              
3             1;
4              
5             package main;
6              
7 1     1   634162 use strict;
  1         3  
  1         39  
8 1     1   6 use Test::More;
  1         3  
  1         9  
9 1     1   36921 use Data::Dumper;
  1         14701  
  1         70  
10 1     1   31009 use File::Temp qw/ tempfile /;
  1         30012  
  1         83  
11 1     1   655 use Outhentic::Story;
  1         3  
  1         2517  
12              
13             $| = 1;
14              
15             sub execute_cmd {
16 0     0     my $cmd = shift;
17 0 0         diag("execute cmd: $cmd") if debug_mod2();
18 0           (system($cmd) == 0);
19             }
20              
21             sub run_story_file {
22              
23 0 0   0     return get_prop('stdout') if defined get_prop('stdout');
24              
25 0           my ($fh, $content_file) = tempfile( DIR => get_prop('test_root_dir') );
26              
27 0 0         if (get_prop('my_stdout')){
28              
29 0           ok(1,"stdout is already set");
30              
31 0 0         open F, ">", $content_file or die $!;
32 0           print F get_prop('my_stdout');
33 0           close F;
34 0           ok(1, "stdout saved to $content_file");
35              
36             }else{
37              
38 0           my $story_file = get_prop('story_file');
39              
40 0           my $st = execute_cmd("perl $story_file 1>$content_file 2>&1 && test -f $content_file");
41              
42 0 0         if ($st) {
    0          
43 0           ok(1, "perl $story_file succeeded");
44             }elsif(ignore_story_err()){
45 0           ok(1, "perl $story_file failed, still continue due to ignore_story_err enabled");
46             }else{
47 0           ok(0, "perl $story_file succeeded");
48 0 0         open CNT, $content_file or die $!;
49 0           my $rdata = join "", ;
50 0           close CNT;
51 0           diag("perl $story_file \n===>\n$rdata");
52             }
53              
54 0           ok(1,"stdout saved to $content_file");
55              
56             }
57              
58 0 0         open F, $content_file or die $!;
59 0           my $cont = '';
60 0           $cont.= $_ while ;
61 0           close F;
62              
63 0           set_prop( stdout => $cont );
64              
65 0           my $debug_bytes = get_prop('debug_bytes');
66              
67 0 0         diag `head -c $debug_bytes $content_file` if debug_mod2();
68              
69 0           return get_prop('stdout');
70             }
71              
72             sub populate_context {
73              
74 0 0   0     return if context_populated();
75              
76 0           my $data = shift;
77 0           my $i = 0;
78              
79 0           my $context = [];
80              
81 0           for my $l ( split /\n/, $data ){
82 0           chomp $l;
83 0           $i++;
84 0 0         $l=":blank_line" unless $l=~/\S/;
85 0           push @$context, [$l, $i];
86             }
87              
88 0           set_prop('context',$context);
89 0           set_prop('context_local',$context);
90              
91 0 0         diag("context populated") if debug_mod2();
92              
93 0           set_prop(context_populated => 1);
94              
95             }
96              
97             sub check_line {
98              
99 0     0     my $pattern = shift;
100 0           my $check_type = shift;
101 0           my $message = shift;
102 0           my $status = 0;
103              
104              
105 0           reset_captures();
106 0           my @captures;
107              
108 0           populate_context( run_story_file() );
109              
110 0 0         diag("lookup $pattern ...") if debug_mod2();
111              
112 0           my @context = @{get_prop('context')};
  0            
113 0           my @context_local = @{get_prop('context_local')};
  0            
114 0           my @context_new = ();
115              
116 0 0         if ($check_type eq 'default'){
    0          
117 0           for my $c (@context_local){
118 0           my $ln = $c->[0]; my $next_i = $c->[1];
  0            
119 0 0         if ( index($ln,$pattern) != -1){
120 0           $status = 1;
121 0           push @context_new, $context[$next_i];
122             }
123             }
124             }elsif($check_type eq 'regexp'){
125 0           for my $c (@context_local){
126 0           my $re = qr/$pattern/;
127 0           my $ln = $c->[0]; my $next_i = $c->[1];
  0            
128              
129 0           my @foo = ($ln =~ /$re/g);
130              
131 0 0         if (scalar @foo){
132 0           push @captures, [@foo];
133 0           $status = 1;
134 0           push @context_new, $context[$next_i];
135             }
136             }
137             }else {
138 0           die "unknown check_type: $check_type";
139             }
140              
141 0           ok($status,$message);
142              
143              
144 0 0         if (debug_mod2()){
145 0           my $k=0;
146 0           for my $ce (@captures){
147 0           $k++;
148 0           diag "captured item N $k";
149 0           for my $c (@{$ce}){
  0            
150 0           diag("\tcaptures: $c");
151             }
152             }
153             }
154              
155 0           set_prop( captures => [ @captures ] );
156              
157 0 0         if (in_block_mode()){
158 0           set_prop( context_local => [@context_new] );
159             }
160              
161             return
162              
163 0           }
164              
165              
166             sub header {
167              
168 0 0   0     if (debug_mod12()) {
169              
170 0           my $project = get_prop('project_root_dir');
171 0           my $story = get_prop('story');
172 0           my $story_type = get_prop('story_type');
173 0           my $story_file = get_prop('story_file');
174 0           my $debug = get_prop('debug');
175 0           my $ignore_story_err = ignore_story_err();
176              
177 0           ok(1, "project: $project");
178 0           ok(1, "story: $story");
179 0           ok(1, "story_type: $story_type");
180 0           ok(1, "debug: $debug");
181 0           ok(1, "ignore story errors: $ignore_story_err");
182             }
183             }
184              
185             sub generate_asserts {
186              
187 0     0     my $filepath_or_array_ref = shift;
188 0           my $write_header = shift;
189              
190 0 0         header() if $write_header;
191              
192 0           my @ents;
193             my @ents_ok;
194 0           my $ent_type;
195              
196 0 0         if ( ref($filepath_or_array_ref) eq 'ARRAY') {
197 0           @ents = @$filepath_or_array_ref
198             }else{
199 0 0         return unless $filepath_or_array_ref;
200 0 0         open my $fh, $filepath_or_array_ref or die $!;
201 0           while (my $l = <$fh>){
202 0           push @ents, $l
203             }
204 0           close $fh;
205             }
206              
207              
208              
209 0           ENTRY: for my $l (@ents){
210              
211 0           chomp $l;
212 0 0         diag $l if runner_debug();
213              
214 0 0         next ENTRY unless $l =~ /\S/; # skip blank lines
215              
216 0 0         if ($l=~ /^\s*#(.*)/) { # skip comments
217 0           next ENTRY;
218             }
219              
220 0 0         if ($l=~ /^\s*begin:\s*$/) { # begin: block marker
221 0 0         diag("begin: block") if debug_mod2();
222 0           set_block_mode();
223 0           next ENTRY;
224             }
225 0 0         if ($l=~ /^\s*end:\s*$/) { # end: block marker
226 0           unset_block_mode();
227 0           populate_context( run_story_file() );
228 0 0         diag("end: block") if debug_mod2();
229 0           set_prop( context_populated => 0); # flush current context
230 0           next ENTRY;
231             }
232              
233 0 0         if ($l=~/^\s*code:\s*(.*)/){
    0          
    0          
    0          
234 0 0         die "unterminated entity found: $ents_ok[-1]" if defined($ent_type);
235 0           my $code = $1;
236 0 0         if ($code=~s/\\\s*$//){
237 0           push @ents_ok, $code;
238 0           $ent_type = 'code';
239 0           next ENTRY; # this is multiline, hold this until last line \ found
240             }else{
241 0           undef $ent_type;
242 0           handle_code($code);
243             }
244             }elsif($l=~/^\s*generator:\s*(.*)/){
245 0 0         die "unterminated entity found: $ents_ok[-1]" if defined($ent_type);
246 0           my $code = $1;
247 0 0         if ($code=~s/\\\s*$//){
248 0           push @ents_ok, $code;
249 0           $ent_type = 'generator';
250 0           next ENTRY; # this is multiline, hold this until last line \ found
251             }else{
252 0           undef $ent_type;
253 0           handle_generator($code);
254             }
255              
256             }elsif($l=~/^\s*regexp:\s*(.*)/){
257 0 0         die "unterminated entity found: $ents_ok[-1]" if defined($ent_type);
258 0           my $re=$1;
259 0           undef $ent_type;
260 0           handle_regexp($re);
261             }elsif(defined($ent_type)){
262 0 0         if ($l=~s/\\\s*$//) {
263 0           push @ents_ok, $l;
264 0           next ENTRY; # this is multiline, hold this until last line \ found
265             }else {
266              
267 1     1   10 no strict 'refs';
  1         1  
  1         1264  
268 0           my $name = "handle_"; $name.=$ent_type;
  0            
269 0           push @ents_ok, $l;
270 0           &$name(\@ents_ok);
271              
272 0           undef $ent_type;
273 0           @ents_ok = ();
274              
275             }
276             }else{
277 0           s{#.*}[], s{\s+$}[], s{^\s+}[] for $l;
278 0           undef $ent_type;
279 0           handle_plain($l);
280             }
281             }
282              
283 0 0         die "unterminated entity found: $ents_ok[-1]" if defined($ent_type);
284              
285             }
286              
287             sub handle_code {
288              
289 0     0     my $code = shift;
290              
291 0 0         unless (ref $code){
292 0           eval $code;
293 0 0         die "code entry eval perl error, code:$code , error: $@" if $@;
294 0 0         diag "handle_code OK. $code" if runner_debug();
295             } else {
296 0           my $code_to_eval = join "\n", @$code;
297 0           eval $code_to_eval;
298 0 0         die "code entry eval error, code:$code_to_eval , error: $@" if $@;
299 0 0         diag "handle_code OK. multiline. $code_to_eval" if runner_debug();
300             }
301              
302             }
303              
304             sub handle_generator {
305              
306 0     0     my $code = shift;
307 0 0         unless (ref $code){
308 0           my $arr_ref = eval $code;
309 0 0         die "generator entry eval error, code:$code , error: $@" if $@;
310 0 0         diag "handle_generator OK. $code" if runner_debug();
311 0           generate_asserts($arr_ref,0);
312             } else {
313 0           my $code_to_eval = join "\n", @$code;
314 0           my $arr_ref = eval $code_to_eval;
315 0 0         die "generator entry eval error, code:$code_to_eval , error: $@" if $@;
316 0 0         diag "handle_generator OK. multiline. $code_to_eval" if runner_debug();
317 0           generate_asserts($arr_ref,0);
318             }
319              
320             }
321              
322             sub handle_regexp {
323              
324 0     0     my $re = shift;
325              
326 0           my $story = get_prop('story');
327              
328 0 0         my $message = in_block_mode() ? "$story stdout matches the | $re" : "$story stdout matches the $re";
329 0           check_line($re, 'regexp', $message);
330 0 0         diag "handle_regexp OK. $re" if runner_debug();
331              
332             }
333              
334             sub handle_plain {
335              
336 0     0     my $l = shift;
337              
338 0           my $story = get_prop('story');
339              
340 0 0         my $message = in_block_mode() ? "$story stdout has | $l" : "$story stdout has $l";
341 0           check_line($l, 'default', $message);
342 0 0         diag "handle_plain OK. $l" if runner_debug();
343             }
344              
345              
346             1;
347              
348              
349             __END__