Los subprocesos de horquillas en las pruebas unitarias de Perl dejan de probar; Prueba :: Arnés saliendo

StackOverflow https://stackoverflow.com/questions/183560

Pregunta

He estado tratando de usar la utilidad / módulo Perl " probar " como un arnés de prueba para algunas pruebas unitarias. Las pruebas unitarias son un poco más '' sistema '' que '' unidad '' ya que necesito bifurcar algunos procesos en segundo plano como parte de la prueba, usando lo siguiente ...

sub SpinupMonitor{
   my $base_dir = shift;
   my $config = shift;

   my $pid = fork();
   if($pid){
      return $pid;
   }else{
      my $cmd = "$base_dir\/..\/bin\/monitor_real.pl -config $config -test";
      close STDOUT;

      exec ($cmd) or die "cannot exec test code [$cmd]\n";
   }
}

sub KillMonitor{

   my $pid = shift;

   print "Killing monitor [$pid]\n";
   kill(1,$pid);
}

Sin embargo, por alguna razón cuando hago que mi archivo .t acelere algunos procesos adicionales, hace que el arnés de prueba se cuelgue al final del primer archivo .t después de que todas las pruebas hayan terminado, en lugar de pasar al siguiente archivo , o salir si solo hay uno.

Al principio me preguntaba si podría ser porque estaba matando a mis subprocesos y dejándolos extintos. Entonces agregué ...

$SIG{CHLD} = \&REAPER;
sub REAPER {
   my $pid = wait;
   $SIG{CHLD} = \&REAPER;
}

Al código. Pero eso no ayuda. De hecho, en un examen cerrado, resulta que mi archivo de prueba de Perl ha salido y ahora es un proceso inactivo y es el script de prueba que no ha cosechado a su hijo. De hecho, cuando agregué una llamada die () al final de mi script de prueba, obtuve ...

# Looks like your test died just after 7.

Entonces mi script salió pero por alguna razón el arnés no se está desenredando.

Confirmé que definitivamente son mis subprocesos los que lo alteran, como cuando los desactivé mientras las pruebas fallaban, el arnés salió correctamente.

¿Hay algo que estoy haciendo mal con la forma en que estoy iniciando mis procesos que podría alterar el arnés de alguna manera?

Gracias

Peter

¿Fue útil?

Solución

¿Asumo que todos sus hijos se han ido antes de que se vaya de la prueba? Porque de lo contrario, puede estar aferrado a STDERR, lo que puede confundir probar. Si pudiera cerrar STDERR, o al menos redirigir a una tubería en su proceso principal, ese puede ser un problema que tenga.

Además de eso, también señalaría que no necesita escapar de las barras diagonales, y si no está utilizando metacaracteres de shell (los espacios no son metacaracteres para perl - piense " *? {} () "), debe ser explícito y crear una lista:

use File::Spec;
my @cmd = File::Spec->catfile($basedir,
                              File::Spec->updir(),
                              qw(bin monitor_real.pl)
                             ),
          -config => $config,
          -test   =>;

close STDOUT;
close STDERR;

exec (@cmd) or die "cannot exec test code [@cmd]\n";

Otros consejos

Tenga en cuenta que no prueba si fork () falló. Debe asegurarse de que $ pid esté definido antes de asumir que "falso" significa "niño".

Debido a que su $ cmd contiene metacaracteres de shell (espacios), Perl en realidad usa un shell cuando llama a exec () . Mientras su monitor está funcionando, hay (1) Perl, (2) un hijo sh -c , y (3) un nieto Perl que ejecuta monitor_real.pl . Lo que eso significa en particular es que cuando llamas a KillMonitor , solo estás matando el shell (porque ese es el PID que tienes) y no el monitor.

También podría estar interesado en ¿Cómo bifurco un proceso de demonio? de las Preguntas frecuentes de Perl.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top