#!/usr/bin/perl

# @author Bodo (Hugo) Barwich
# @version 2020-09-26
# @package Test for the Process::SubProcess::Group Module
# @subpackage test_subprocess.t

# This Module runs tests on the Process::SubProcess::Group Module
#
#---------------------------------
# Requirements:
# - The Perl Module "Process::SubProcess::Group" must be installed
#



use warnings;
use strict;

use Cwd qw(abs_path);

use Time::HiRes qw(gettimeofday);

use Test::More;

BEGIN
{
  use lib "lib";
  use lib "../lib";
}  #BEGIN

require_ok('Process::SubProcess');
require_ok('Process::SubProcess::Group');

use Process::SubProcess;
use Process::SubProcess::Group;



my $smodule = "";
my $spath = abs_path($0);


($smodule = $spath) =~ s/.*\/([^\/]+)$/$1/;
$spath =~ s/^(.*\/)$smodule$/$1/;


my $stestscript = "test_script.pl";
my $itestpause = 3;
my $iteststatus = 4;

my $procgroup = undef;
my $proctest = undef;

my $rscriptlog = undef;
my $rscripterror = undef;
my $iscriptstatus = -1;



#------------------------
#Test: 'Process::SubProcess::Group::Run'

my $itm = -1;
my $itmstrt = -1;
my $itmend = -1;
my $itmexe = -1;

my $iprc = -1;
my $iprccnt = -1;


print "Test: 'Process::SubProcess::Group::Run' do ...\n";

$procgroup = Process::SubProcess::Group::->new;

$itestpause = 2;

$proctest = Process::SubProcess::->new(('name' => 'test-script:2s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause));

$procgroup->add($proctest);

$itestpause = 3;

$proctest = Process::SubProcess::->new(('name' => 'test-script:3s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause));

$procgroup->add($proctest);

$itestpause = 1;

$proctest = Process::SubProcess::->new(('name' => 'test-script:1s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause));

$procgroup->add($proctest);

$iprccnt = $procgroup->getProcessCount;

is($iprccnt, 3, "scripts (count: '$iprccnt'): added correctly");


$itmstrt = gettimeofday();

print "Process Group Execution Start - Time Now: '$itmstrt' s\n";

is($procgroup->Run, 1, "Process Group Execution: Execution correct");

$itmend = gettimeofday();

$itm = ($itmend - $itmstrt) * 1000;

print "Process Group Execution End - Time Now: '$itmend' s\n";

print "Process Group Execution finished in '$itm' ms\n";


for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    print("Process ", $proctest->getNameComplete, ":\n");

    $rscriptlog = $proctest->getReportString;
    $rscripterror = $proctest->getErrorString;
    $iscriptstatus = $proctest->getProcessStatus;

    print("ERROR CODE: '", $proctest->getErrorCode, "'\n");
    print("EXIT CODE: '$iscriptstatus'\n");

    if(defined $rscriptlog)
    {
      print("STDOUT: '$$rscriptlog'\n");
    }
    else
    {
      isnt($rscriptlog, undef, "STDOUT was captured");
    } #if(defined $rscriptlog)

    if(defined $rscripterror)
    {
      print("STDERR: '$$rscripterror'\n");
    }
    else
    {
      isnt($rscripterror, undef, "STDERR was captured");
    } #if(defined $rscripterror)
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

print "\n";



#------------------------
#Test: 'Process::SubProcess::Group Profiling'

print "Test: 'Process::SubProcess::Group Profiling' do ...\n";

$procgroup = Process::SubProcess::Group::->new(('check' => 2));

$itestpause = 3;

$proctest = Process::SubProcess::->new(('name' => 'test-script:3s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 5;

$proctest = Process::SubProcess::->new(('name' => 'test-script:5s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 9;

$proctest = Process::SubProcess::->new(('name' => 'test-script:9s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$iprccnt = $procgroup->getProcessCount;

is($iprccnt, 3, "scripts (count: '$iprccnt'): added correctly");


$itmstrt = gettimeofday();

print "Process Group Execution Start - Time Now: '$itmstrt' s\n";

is($procgroup->Run, 1, "Process Group Execution: Execution correct");

$itmend = gettimeofday();

$itm = ($itmend - $itmstrt) * 1000;

print "Process Group Execution End - Time Now: '$itmend' s\n";

print "Process Group Execution finished in '$itm' ms\n";


for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    print("Process ", $proctest->getNameComplete, ":\n");

    $rscriptlog = $proctest->getReportString;
    $rscripterror = $proctest->getErrorString;
    $iscriptstatus = $proctest->getProcessStatus;

    isnt($proctest->getExecutionTime, -1 , "Execution Time was measured");

    print("Read Timeout: '", $proctest->getReadTimeout, "'\n");
    print("Execution Time: '", $proctest->getExecutionTime, "'\n");

    print("EXIT CODE: '$iscriptstatus'\n");

    if(defined $rscriptlog)
    {
      print("STDOUT: '$$rscriptlog'\n");
    }
    else
    {
      isnt($rscriptlog, undef, "STDOUT was captured");
    } #if(defined $rscriptlog)

    if(defined $rscripterror)
    {
      print("STDERR: '$$rscripterror'\n");
    }
    else
    {
      isnt($rscripterror, undef, "STDERR was captured");
    } #if(defined $rscripterror)
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

print "\n";


#------------------------
#Test: 'Process::SubProcess::Group Profiling Quiet'

my $itesttime = -1;


print "Test: 'Process::SubProcess::Group Profiling Quiet' do ...\n";

$procgroup = Process::SubProcess::Group::->new(('check' => 2));

$stestscript = 'quiet_script.pl';
$itestpause = 3;

$proctest = Process::SubProcess::->new(('name' => 'quiet-script:3s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 5;

$proctest = Process::SubProcess::->new(('name' => 'quiet-script:5s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 9;

$proctest = Process::SubProcess::->new(('name' => 'quiet-script:9s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$iprccnt = $procgroup->getProcessCount;

is($iprccnt, 3, "scripts (count: '$iprccnt'): added correctly");

$procgroup->setCheckInterval(6);

isnt($procgroup->getCheckInterval, -1, "Read Timeout activated");


$itmstrt = gettimeofday();

print "Process Group Execution Start - Time Now: '$itmstrt' s\n";

is($procgroup->Run, 1, "Process Group Execution: Execution correct");

$itmend = gettimeofday();

$itm = ($itmend - $itmstrt) * 1000;

print "Process Group Execution End - Time Now: '$itmend' s\n";

print "Process Group Execution finished in '$itm' ms\n";


for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    print("Process ", $proctest->getNameComplete, " finished with [" . $proctest->getErrorCode . "]:\n");

    $rscriptlog = $proctest->getReportString;
    $rscripterror = $proctest->getErrorString;
    $iscriptstatus = $proctest->getProcessStatus;

    isnt($proctest->getExecutionTime, -1 , "Execution Time was measured");

    print("Read Timeout: '", $proctest->getReadTimeout, "'\n");
    print("Execution Time: '", $proctest->getExecutionTime, "'\n");

    print("ERROR CODE: '", $proctest->getErrorCode, "'\n");
    print("EXIT CODE: '$iscriptstatus'\n");

    if(defined $rscriptlog)
    {
      print("STDOUT: '$$rscriptlog'\n");
    }
    else
    {
      isnt($rscriptlog, undef, "STDOUT was captured");
    } #if(defined $rscriptlog)

    if(defined $rscripterror)
    {
      print("STDERR: '$$rscripterror'\n");
    }
    else
    {
      isnt($rscripterror, undef, "STDERR was captured");
    } #if(defined $rscripterror)
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

print "\n";


#------------------------
#Test: 'Process::SubProcess::Group Execution Timeout'

my $iprctmoutcnt = -1;


print "Test: 'Process::SubProcess::Group Execution Timeout' do ...\n";

$procgroup = Process::SubProcess::Group::->new(('timeout' => 7));

$stestscript = "test_script.pl";
$itestpause = 3;

$proctest = Process::SubProcess::->new(('name' => 'test-script:3s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 5;

$proctest = Process::SubProcess::->new(('name' => 'test-script:5s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 13;

$proctest = Process::SubProcess::->new(('name' => 'test-script:13s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$iprccnt = $procgroup->getProcessCount;

is($iprccnt, 3, "scripts (count: '$iprccnt'): added correctly");

$procgroup->setCheckInterval(6);

isnt($procgroup->getCheckInterval, -1, "Check Interval activated");
isnt($procgroup->getTimeout, -1, "Execution Timeout activated");


$itmstrt = gettimeofday();

print "Process Group Execution Start - Time Now: '$itmstrt' s\n";

is($procgroup->Run, 0, "Process Group Execution: Execution failed as expected");

$itmend = gettimeofday();

$itm = ($itmend - $itmstrt) * 1000;

print "Process Group Execution End - Time Now: '$itmend' s\n";

print "Process Group Execution finished in '$itm' ms\n";

print("Process Group ERROR CODE: '" .  $procgroup->getErrorCode .  "'\n");

is($procgroup->getErrorCode, 4, "Process Group Execution: ERROR CODE is correct");

print("Process Group STDOUT: '" . ${$procgroup->getReportString} . "'\n");
print("Process Group STDERR: '" . ${$procgroup->getErrorString} . "'\n");

$iprctmoutcnt = 0 if($procgroup->getErrorCode == 4);

for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    print("Process ", $proctest->getNameComplete, " finished with [" . $proctest->getErrorCode . "]:\n");

    $rscriptlog = $proctest->getReportString;
    $rscripterror = $proctest->getErrorString;
    $iscriptstatus = $proctest->getProcessStatus;

    print("ERROR CODE: '", $proctest->getErrorCode, "'\n");
    print("EXIT CODE: '$iscriptstatus'\n");

    if($proctest->getErrorCode == 4)
    {
      $iprctmoutcnt++ ;

      is($proctest->getExecutionTime, -1, "Execution Time not measured as expected");
    }
    else  #Timeout Error
    {
      isnt($proctest->getExecutionTime, -1, "Execution Time was measured");
    } #if($proctest->getErrorCode == 4)

    print("Read Timeout: '", $proctest->getReadTimeout, "'\n");
    print("Execution Time: '", $proctest->getExecutionTime, "'\n");

    if(defined $rscriptlog)
    {
      print("STDOUT: '$$rscriptlog'\n");
    }
    else
    {
      isnt($rscriptlog, undef, "STDOUT was captured");
    } #if(defined $rscriptlog)

    if(defined $rscripterror)
    {
      print("STDERR: '$$rscripterror'\n");
    }
    else
    {
      isnt($rscripterror, undef, "STDERR was captured");
    } #if(defined $rscripterror)
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

is($iprctmoutcnt, 1, "'1' Process timed out as expected");

print("Process Group Execution Timeout - Count: '$iprctmoutcnt'\n");

print "\n";


#------------------------
#Test: 'Process::SubProcess::Group::Wait() Method'

$iprctmoutcnt = -1;


print "Test: 'Process::SubProcess::Group::Wait() Method' do ...\n";

$procgroup = Process::SubProcess::Group::->new(('timeout' => 7));

$stestscript = "test_script.pl";
$itestpause = 3;

$proctest = Process::SubProcess::->new(('name' => 'test-script:3s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 5;

$proctest = Process::SubProcess::->new(('name' => 'test-script:5s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$itestpause = 13;

$proctest = Process::SubProcess::->new(('name' => 'test-script:13s'
  , 'command' => $spath . $stestscript . ' ' . $itestpause
  , 'profiling' => 1));

is($proctest->isProfiling, 1, 'Profiling activated');

$procgroup->add($proctest);

$iprccnt = $procgroup->getProcessCount;

is($iprccnt, 3, "scripts (count: '$iprccnt'): added correctly");

$procgroup->setCheckInterval(6);

isnt($procgroup->getCheckInterval, -1, "Check Interval activated");
isnt($procgroup->getTimeout, -1, "Execution Timeout activated");


$itmstrt = gettimeofday();

print "Process Group Execution Start - Time Now: '$itmstrt' s\n";

for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    is($proctest->Launch, 1, "Process No. '$iprc': Launch succeeded");
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

is($procgroup->getRunningCount, 3, "Process Group Execution: All Processes are launched");

is($procgroup->Wait(), 0, "Process Group Execution: Execution failed as expected");

$itmend = gettimeofday();

$itm = ($itmend - $itmstrt) * 1000;

print "Process Group Execution End - Time Now: '$itmend' s\n";

print "Process Group Execution finished in '$itm' ms\n";

print("Process Group ERROR CODE: '" .  $procgroup->getErrorCode .  "'\n");

is($procgroup->getErrorCode, 4, "Process Group Execution: ERROR CODE is correct");

print("Process Group STDOUT: '" . ${$procgroup->getReportString} . "'\n");
print("Process Group STDERR: '" . ${$procgroup->getErrorString} . "'\n");

$iprctmoutcnt = 0 if($procgroup->getErrorCode == 4);

for($iprc = 0; $iprc < $iprccnt; $iprc++)
{
  $proctest = $procgroup->getiProcess($iprc);

  isnt($proctest, undef, "Process No. '$iprc': Listed correctly");

  if(defined $proctest)
  {
    print("Process ", $proctest->getNameComplete, " finished with [" . $proctest->getErrorCode . "]:\n");

    $rscriptlog = $proctest->getReportString;
    $rscripterror = $proctest->getErrorString;
    $iscriptstatus = $proctest->getProcessStatus;

    print("ERROR CODE: '", $proctest->getErrorCode, "'\n");
    print("EXIT CODE: '$iscriptstatus'\n");

    if($proctest->getErrorCode == 4)
    {
      $iprctmoutcnt++ ;

      is($proctest->getExecutionTime, -1, "Execution Time not measured as expected");
    }
    else  #Timeout Error
    {
      isnt($proctest->getExecutionTime, -1, "Execution Time was measured");
    } #if($proctest->getErrorCode == 4)

    print("Read Timeout: '", $proctest->getReadTimeout, "'\n");
    print("Execution Time: '", $proctest->getExecutionTime, "'\n");

    if(defined $rscriptlog)
    {
      print("STDOUT: '$$rscriptlog'\n");
    }
    else
    {
      isnt($rscriptlog, undef, "STDOUT was captured");
    } #if(defined $rscriptlog)

    if(defined $rscripterror)
    {
      print("STDERR: '$$rscripterror'\n");
    }
    else
    {
      isnt($rscripterror, undef, "STDERR was captured");
    } #if(defined $rscripterror)
  } #if(defined $proctest)
} #for($iprc = 0; $iprc < $iprccnt; $iprc++)

is($iprctmoutcnt, 1, "'1' Process timed out as expected");

print("Process Group Execution Timeout - Count: '$iprctmoutcnt'\n");

print "\n";


done_testing();
