我一直在尝试使用Perl实用程序/模块"证明"作为一些单元测试的测试工具.单元测试比"单元"更加"系统",因为我需要将一些后台进程分解为测试的一部分,使用以下...
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); }
但是出于某种原因,当我让我的.t文件启动一些额外的进程时,它会导致测试工具在所有测试完成后挂在第一个.t文件的末尾,而不是转到下一个文件,或者退出如果只有一个.
起初我想知道是否可能是因为我正在杀死我的子流程并让它们不复存在.所以我补充说..
$SIG{CHLD} = \&REAPER; sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; }
到代码.但这没有用.事实上,在封闭式检查中,我发现我的perl测试文件已经退出并且现在已经不存在了,并且它是证明包装器脚本没有收到它的孩子.事实上,当我在测试脚本的末尾添加了一个die()调用时,我得到了......
# Looks like your test died just after 7.
所以我的脚本退出了,但由于某种原因,线束没有解开.
我确实确认我的子流程肯定是令我感到不安的,因为我在禁用它们的同时测试失败,线束正确退出.
我在启动可能以某种方式扰乱线束的过程的方式有什么问题吗?
谢谢
彼得
请注意,您不测试是否fork()
失败.在假设"false"表示"child"之前,您需要确定$pid
是否已定义.
因为你$cmd
包含shell元字符(空格),Perl实际上在你调用时使用了shell exec()
.当您的显示器运行时,有(1)Perl,(2)一个孩子sh -c
,(3)孙子Perl正在运行monitor_real.pl
.这特别意味着当你打电话时KillMonitor
,你只是在杀死shell(因为那是你拥有的PID),而不是监视器.
您可能还对如何分叉守护进程感兴趣?来自Perl FAQ.
我假设你的孩子在离开考试之前已经退出了吗?因为否则,它可能会挂在STDERR上,这可能会混淆证明.如果您可以关闭STDERR,或者至少重定向到父进程中的管道,那么这可能是您遇到的一个问题.
除此之外,我还要指出你不需要转义正斜杠,如果你没有使用shell元字符(空格不是perl的元字符 - 想想" *?{}()
"),你应该明确并创建一个列表:
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";