Brian Candler
5/3/2007 8:00:00 PM
On Fri, May 04, 2007 at 01:11:39AM +0900, John Miller wrote:
> Brian Candler wrote:
> > On Thu, May 03, 2007 at 11:54:37AM +0900, John Miller wrote:
> >> either.
> > I suggest you post your code; modify it so the process it calls via
> > popen is
> > "sleep 15" or something like that.
> >
> > I've never had problems testing threads; but I *have* had problems when
> > testing code which forks another process (which may include popen).
> >
> > The problem was that the child process inherited all the Test::Unit
> > stuff,
> > including its atexit handler. I think the solution was to call exit! at
> > the
> > end of the child, but I can't remember exactly.
>
> Actually popen is easy to get around. I rewrote it for the test simply
> return a StringIO like object instead of a new process. I can test the
> process that is called separately.
>
> Per request here is the code in question
>
> This is the method I'm testing:
>
> #Attempt to kill the process 'pid' after
> #'time' seconds.
> def terminate_process_after(pid,time)
> Thread.new do
> sleep time
> begin
> cross_platform_end_process(pid)
> rescue
> end
> end
> end
Hmm, that's not what I meant. I meant the full code, complete with test, so
it could be run and seen to fail.
It's hard for me to replicate exactly what you're talking about, since
IO.popen doesn't return a pid.
But writing an example using fork and exec works perfectly for me - see
below. And as you can see, it uses a thread in just the way you seem to be.
Regards,
Brian.
--- 8< ------------------------------------------------------------------
require 'test/unit'
class Foo
def terminate_process_after(pid,time)
Thread.new do
sleep time
Process.kill 'TERM', pid
end
end
def doit(cmd)
fork { exec(cmd) } # returns pid
end
end
class TestFoo < Test::Unit::TestCase
def setup
@foo = Foo.new
end
def test_single
pid = @foo.doit("sleep 4")
Process.waitpid(pid)
end
def test_short
pid = @foo.doit("sleep 4")
@foo.terminate_process_after(pid, 2)
Process.waitpid(pid)
end
def test_long
pid = @foo.doit("sleep 4")
@foo.terminate_process_after(pid, 6)
Process.waitpid(pid)
end
end