File Coverage

blib/lib/Gruntmaster/Daemon/Format.pm
Criterion Covered Total %
statement 39 95 41.0
branch 0 26 0.0
condition 0 12 0.0
subroutine 13 18 72.2
pod 1 4 25.0
total 53 155 34.1


line stmt bran cond sub pod time code
1             package Gruntmaster::Daemon::Format;
2              
3 2     2   59 use 5.014000;
  2         7  
  2         77  
4 2     2   11 use strict;
  2         3  
  2         59  
5 2     2   10 use warnings;
  2         3  
  2         122  
6 2     2   10 use parent qw/Exporter/;
  2         3  
  2         12  
7 2     2   2821 no if $] > 5.017011, warnings => 'experimental::smartmatch';
  2         201  
  2         15  
8              
9 2     2   2826 use POSIX qw//;
  2         32307  
  2         66  
10 2     2   20 use File::Basename qw/fileparse/;
  2         3  
  2         229  
11 2     2   2626 use File::Slurp qw/write_file/;
  2         21338  
  2         216  
12 2     2   23 use Gruntmaster::Daemon::Constants qw/TLE OLE DIED NZX/;
  2         4  
  2         115  
13 2     2   3827 use Time::HiRes qw/alarm/;
  2         5206  
  2         10  
14 2     2   5514 use List::MoreUtils qw/natatime/;
  2         3173  
  2         179  
15 2     2   2806 use Log::Log4perl qw/get_logger/;
  2         135434  
  2         18  
16 2     2   1981 use IPC::Signal qw/sig_name sig_num/;
  2         1421  
  2         5550  
17              
18             our $VERSION = "5999.000_004";
19             our @EXPORT_OK = qw/prepare_files/;
20              
21             ##################################################
22              
23             sub command_and_args{
24 0     0 0   my ($format, $basename) = @_;
25              
26 0           given($format) {
27 0           "./$basename" when [qw/C CPP GCCGO GOLANG HASKELL PASCAL/];
28 0           "./$basename.exe" when 'MONO';
29 0           java => $basename when 'JAVA';
30 0           perl => $basename when 'PERL';
31 0           python => $basename when 'PYTHON';
32 0           default { die "Don't know how to execute format $format" }
  0            
33             }
34             }
35              
36             sub mkrun{
37 0     0 0   my $format = shift;
38             sub{
39 0     0     local *__ANON__ = 'mkrun_runner';
40 0           my ($name, %args) = @_;
41 0           get_logger->trace("Running $name...");
42 0           my $basename = fileparse $name, qr/\.[^.]*/;
43 0   0       my $ret = fork // die 'Cannot fork';
44 0 0         if ($ret) {
45 0           my $tle;
46 0           local $SIG{ALRM} = sub { kill KILL => $ret; $tle = 1};
  0            
  0            
47 0 0         alarm $args{timeout} if exists $args{timeout};
48 0           waitpid $ret, 0;
49 0           alarm 0;
50 0           my $sig = $? & 127;
51 0           my $signame = sig_name $sig;
52 0 0         die [TLE, "Time Limit Exceeded"] if $tle;
53 0 0 0       die [OLE, 'Output Limit Exceeded'] if $sig && $signame eq 'XFSZ';
54 0 0 0       die [DIED, "Crash (SIG$signame)"] if $sig && $signame ne 'PIPE';
55 0 0         die [NZX, "Non-zero exit status: " . ($? >> 8)] if $? >> 8;
56             } else {
57 0 0         my @fds = exists $args{fds} ? @{$args{fds}} : ();
  0            
58 0           $^F = 50;
59 0           POSIX::close $_ for 0 .. $^F;
60 0           my $it = natatime 2, @fds;
61 0           while (my ($fd, $file) = $it->()) {
62 0 0         open my $fh, $file or die $!;
63 0           my $oldfd = fileno $fh;
64 0 0         if ($oldfd != $fd) {
65 0 0         POSIX::dup2 $oldfd, $fd or die $!;
66 0 0         POSIX::close $oldfd or die $!;
67             }
68             }
69 0 0 0       exec 'gruntmaster-exec', $args{mlimit} // 0, $args{olimit} // 0, command_and_args($format, $basename), exists $args{args} ? @{$args{args}} : ();
  0   0        
70 0           exit 42
71             }
72             }
73 0           }
74              
75             sub prepare{
76 0     0 0   my ($name, $format) = @_;
77 0           get_logger->trace("Preparing file $name...");
78              
79 0           $Gruntmaster::Daemon::errors .= `gruntmaster-compile $format $name 2>&1`;
80 0           $Gruntmaster::Daemon::errors .= "\n";
81 0 0         die 'Compile error' if $?
82             }
83              
84             sub prepare_files{
85 0     0 1   my $meta = shift;
86              
87 0           for my $file (values $meta->{files}) {
88 0           my ($format, $name, $content) = @{$file}{qw/format name content/};
  0            
89              
90 0           $file->{run} = mkrun($format);
91 0           write_file $name, $content;
92 0           prepare $name, $format;
93             }
94             }
95              
96             1;
97             __END__