File Coverage

blib/lib/Test/C2FIT.pm
Criterion Covered Total %
statement 27 172 15.7
branch 0 70 0.0
condition 0 9 0.0
subroutine 9 33 27.2
pod 2 3 66.6
total 38 287 13.2


line stmt bran cond sub pod time code
1             package Test::C2FIT;
2              
3             #use 5.008006;
4 1     1   1532 use Test::C2FIT::FileRunner;
  1         5  
  1         29  
5 1     1   738 use Test::C2FIT::WikiRunner;
  1         3  
  1         21  
6 1     1   6 use Exporter();
  1         2  
  1         16  
7 1     1   2578 use Getopt::Std;
  1         42  
  1         83  
8             @ISA = qw(Exporter);
9             @EXPORT = qw(file_runner wiki_runner fit_shell);
10 1     1   5 use strict;
  1         2  
  1         29  
11 1     1   5 use warnings;
  1         2  
  1         428  
12              
13             our $VERSION = '0.08';
14              
15             sub file_runner {
16 0     0 1   my $param = {};
17 0 0         die "unsupported param!" unless getopt( "L:", $param );
18 0           local $SIG{'__WARN__'} = _commonLogging( $param->{L} );
19              
20 0 0         unshift( @INC, '.' ) unless grep { /^\.$/ } @INC;
  0            
21 0           Test::C2FIT::FileRunner->new()->run(@ARGV);
22             }
23              
24             sub wiki_runner {
25 0     0 0   my $param = {};
26 0 0         die "unsupported param!" unless getopt( "L:", $param );
27 0           local $SIG{'__WARN__'} = _commonLogging( $param->{L} );
28              
29 0 0         unshift( @INC, '.' ) unless grep { /^\.$/ } @INC;
  0            
30 0           Test::C2FIT::WikiRunner->new()->run(@ARGV);
31             }
32              
33             sub fit_shell {
34 0     0 1   my $shell = Test::C2FIT::_Shell->new();
35 0           $shell->init;
36 0           $shell->runShell(*STDIN);
37             }
38              
39             sub _commonLogging {
40 0     0     my $loglevel = shift;
41 0 0         $loglevel = 3 unless defined($loglevel);
42              
43             return sub {
44 0     0     local ( $_, $&, $1 );
45              
46 0 0 0       if ( defined( $_[0] ) && $_[0] =~ /^(\d+)/ ) {
47 0 0         return unless $1 >= $loglevel;
48             }
49              
50             # my ($sec,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime(time);
51             # $mon++;
52             # $year = $year + 1900;
53             # print STDERR sprintf("%02d.%02d.%04d %02d:%02d:%02d ",$mday,$mon,$year,$hour,$min,$sec);
54 0           print STDERR @_;
55 0           };
56             }
57              
58             #
59             # (help-) Package implementing an interactive shell
60             #
61             {
62              
63             package Test::C2FIT::_Shell;
64 1     1   6 use Config;
  1         1  
  1         44  
65 1     1   5 use strict;
  1         1  
  1         30  
66 1     1   4 use warnings;
  1         2  
  1         2261  
67              
68             sub new {
69 0     0     my $pkg = shift;
70             my $self = {
71             lastCmd => undef,
72             perlBinary => $Config{perlpath},
73             options => {
74             input => ".",
75             output => ".",
76             inc => ".",
77             perl_opt => undef,
78             log_level => undef,
79             runner => 'file_runner',
80             verbose => 0,
81             },
82             cmdDispatch => {
83             help => \&Test::C2FIT::_Shell::help,
84             show => \&Test::C2FIT::_Shell::show,
85             set => \&Test::C2FIT::_Shell::set,
86             run => \&Test::C2FIT::_Shell::run,
87             runall => \&Test::C2FIT::_Shell::runall,
88 0     0     nop => sub { 1 },
89 0     0     quit => sub { undef },
90             },
91 0           parseRunDispatch => {
92             rerun => \&Test::C2FIT::_Shell::rerun,
93             infile => \&Test::C2FIT::_Shell::runInfile,
94             files => \&Test::C2FIT::_Shell::runFiles,
95             inout => \&Test::C2FIT::_Shell::runInOut,
96             }
97             };
98 0           return bless $self, $pkg;
99             }
100              
101             sub init {
102 0     0     my $self = shift;
103              
104             #
105             # check if input/output/lib exists
106             #
107 0           my $v = {};
108              
109 0 0         $v->{input} = "input" if ( -d "./input" );
110 0 0         $v->{output} = "output" if ( -d "./output" );
111 0 0         $v->{inc} = "lib" if ( -d "./lib" );
112              
113 0 0         if ( scalar(%$v) ) {
114 0           while ( my ( $ik, $iv ) = each(%$v) ) {
115 0           $self->{options}->{$ik} = $iv;
116             }
117             $self->msg(
118 0           "INFO: input/ouptut/lib diretories found, using them!\n");
119 0           $self->show;
120             }
121             }
122              
123             sub help {
124 0     0     print <<'_EOH_'; return 1;
  0            
125             # Supported commands:
126             # help - show this help
127             # show - show variables
128             # set - set operational variables
129             # input - directory where html files are searched
130             # output - directory where result html will be written
131             # inc - INC path. This will be added to the perl-process
132             # upon creation (perl -Ip1 -Ip2 etc.)
133             # multiple Entries should be separated either by
134             # colon (:) or by semicolon, e.g. lib:.:../test
135             # if @ is given, then then contents of @INC of the
136             # fit_shell-process will be set
137             # perl_opt - optional perl-parameters to the perl process.
138             # e.g. -d for debugging
139             # log_level - will be passed to the runner
140             # runner - either file_runner or wiki_runner
141             # verbose - either 0 or 1. When 1, then the command actually
142             # run will be printed too
143             # run - run a document. There are different ways to specify it:
144             # run BinaryChop - runs a file named $input/BinaryChop.html
145             # output goes to $output/BinaryChop.html
146             # run BinaryChop out - runs a file named $input/BinaryChop
147             # (without extension!!!)
148             # output goes to $output/out (without extension!)
149             #
150             # run - rerun last run command
151             #
152             # run *.htm* - run all files $input/*.htm*
153             # (same as runall)
154             # run a*.html b*.html - run all files $input/a*.html $input/b*.html
155             # (Difference to the other two-Param run-call:
156             # here, wildcards are used)
157             # runall - same as run *.htm*
158             #
159             # quit - terminate this shell
160             #
161             # For each run, a new perl process is started.
162             #
163             # There are some shortcuts/aliases too:
164             #
165             # ! is an alias for "run"
166             # [EMPTY LINE] (i.e. just pressing the enter key) rerun last run
167             #
168             # Lines starting with # will be ignored
169             #
170             # All output of the fit_shell starts with "#", so you can easily eliminate
171             # it (e.g. grep -v "^#")
172             #
173             _EOH_
174             }
175              
176             sub msg {
177 0     0     my $self = shift;
178 0           print "# ", @_;
179 0           1;
180             }
181              
182             sub show {
183 0     0     my $self = shift;
184 0           my @k = sort keys %{ $self->{options} };
  0            
185              
186 0           for my $k (@k) {
187 0           my $v = $self->{options}->{$k};
188 0 0         $v = "" unless defined($v);
189 0           print sprintf( "# %10s: %s\n", $k, $v );
190             }
191 0           1;
192             }
193              
194             sub set {
195 0     0     my ( $self, $rest ) = @_;
196 0 0         return $self->msg("WARN: wrong syntax for set!\n")
197             unless $rest =~ /(\S+)(?:\s+(\S.*))?$/;
198              
199 0           my $key = $1;
200 0           my $val = $2;
201              
202 0 0         return $self->msg("WARN: invalid variable $key!\n")
203             unless exists $self->{options}->{$key};
204              
205 0 0 0       if ( $key eq "inc" && $val eq "@" ) {
206 0           $val = join( ":", @INC );
207             }
208              
209 0           $self->{options}->{$key} = $val;
210 0           $self->{lastCmd} = undef;
211 0           1;
212             }
213              
214             sub runall {
215 0     0     my $self = shift;
216 0           $self->run("*.htm*");
217             }
218              
219             sub run {
220 0     0     my ( $self, $rest ) = @_;
221 0           my $dispatch = $self->{parseRunDispatch};
222              
223 0           my ( $key, @vals ) = $self->parseRunCmd($rest);
224 0 0         die "internal error. unknown state: $key\n"
225             unless exists $dispatch->{$key};
226              
227 0           my $code = $dispatch->{$key};
228 0           return $code->( $self, @vals );
229             }
230              
231             sub rerun {
232 0     0     my $self = shift;
233 0 0         return $self->msg("WARN: no cmd to rerun!\n")
234             unless defined( $self->{lastCmd} );
235 0           return $self->_run( $self->{lastCmd} );
236             }
237              
238             #
239             # runInOut($in,$out) - both filenames with path and suffix
240             #
241             sub runInOut {
242 0     0     my ( $self, $in, $out ) = @_;
243              
244 0 0         return $self->msg("WARN: in and out identical: $in Will be ignored!\n'")
245             if $in eq $out;
246              
247 0           my $cmd = $self->_buildCmd;
248 0           $cmd .= " $in $out";
249 0           return $self->_run($cmd);
250             }
251              
252             #
253             # runInfile (path+filename) * optionally without the .html suffix
254             #
255             sub runInfile {
256 0     0     my ( $self, $in ) = @_;
257 0           my $input = quotemeta( $self->{options}->{input} );
258 0           my $output = $self->{options}->{output};
259              
260 0 0         $in .= ".html" unless $in =~ /\.html$/i;
261 0           my $out = $in;
262 0           $out =~ s/^$input/$output/;
263              
264 0           return $self->runInOut( $in, $out );
265             }
266              
267             #
268             # runFiles(@files) - list of input file names with path and extension
269             #
270             sub runFiles {
271 0     0     my ( $self, @files ) = @_;
272 0           for my $f (@files) {
273 0           $self->runInfile($f);
274             }
275 0           1;
276             }
277              
278             sub _run {
279 0     0     my ( $self, $cmd ) = @_;
280 0 0         die "no cmd given!" unless defined($cmd);
281 0           $self->{lastCmd} = $cmd;
282 0 0         $self->msg("# CMD:$cmd\n") if $self->{options}->{verbose};
283 0           system($cmd);
284 0           1;
285             }
286              
287             sub _buildCmd { # setup the command up to ARGV
288 0     0     my $self = shift;
289 0           my $cmd = $self->{perlBinary};
290 0           my $options = $self->{options};
291              
292 0 0         $cmd .= " " . $options->{perl_opt} . " "
293             if defined( $options->{perl_opt} );
294              
295 0 0         if ( defined( $options->{inc} ) ) {
296 0           my @inc = split( /[:;]/, $options->{inc} );
297 0           my $inc = " -I" . join( " -I", @inc );
298 0           $cmd .= $inc;
299             }
300              
301 0           $cmd .= " -MTest::C2FIT -e " . $options->{runner} . " -- ";
302              
303 0           my $logLevel = $options->{log_level};
304 0 0         $cmd .= " -L $logLevel " if defined($logLevel);
305              
306 0           return $cmd;
307             }
308              
309             sub parseRunCmd {
310 0     0     my ( $self, $rest ) = @_;
311 0           my $input = $self->{options}->{input};
312 0           my $output = $self->{options}->{output};
313 0           my $hasWildcards = 0;
314 0           my @files = ();
315              
316 0 0         return ("rerun") unless defined($rest);
317              
318 0 0         my @items = map { /\*/ && $hasWildcards++; $_ } split /\s+/, $rest;
  0            
  0            
319              
320 0 0         if ($hasWildcards) {
321 0           for my $item (@items) {
322 0           push( @files, glob("$input/$item") );
323             }
324 0           return ( "files", @files );
325             }
326 0 0         if ( 2 == @items ) {
327 0           return ( "inout", "$input/$items[0]", "$output/$items[1]" );
328             }
329 0           return ( "infile", "$input/$items[0]" );
330             }
331              
332             sub runShell { # main loop of fit_shell
333 0     0     my ( $self, $inFH ) = @_;
334 0           my $line;
335 0           my $dispatch = $self->{cmdDispatch};
336 0 0         my $prompt = ( -t "$inFH" ) ? "fit> " : "";
337              
338 0           $| = 1;
339              
340 0           print $prompt;
341 0           while ( $line = <$inFH> ) {
342 0           $line =~ s/(\012\015?|\015\012?)$//;
343 0           my ( $cmd, $rest ) = $self->parseCmd($line);
344              
345 0 0         die "internal error. Unknown command/state: $cmd\n"
346             unless exists $dispatch->{$cmd};
347              
348 0           my $code = $dispatch->{$cmd};
349 0           my $rv = $code->( $self, $rest );
350 0 0         last unless $rv;
351 0           print $prompt;
352             }
353             }
354              
355             sub parseCmd {
356 0     0     my ( $self, $line ) = @_;
357              
358 0 0 0       return ( "run", undef ) if !defined($line) || $line eq "";
359 0 0         return ("nop") if $line =~ /^\s*#/;
360              
361 0           $line =~ s/^\s+//;
362 0           $line =~ s/\s+$//;
363              
364 0 0         if ( $line =~ /^!\s*(\S.*)?$/ ) { # ! is alias for "run"
365 0           return ( "run", $1 );
366             }
367 0 0         if ( $line =~ /^(\w+)\b\s*(\S.*)?$/ ) {
368 0           return ( $1, $2 );
369             }
370 0           return ("nop");
371             }
372              
373             1;
374             };
375              
376             1;
377              
378             __END__