At 04:23 PM 6/6/2005 -0700, Brian Kirsch wrote:
Ok sounds good. Especially if you wanna do the work of implementing the
mock reactor :)
Well, I took a look this morning, and implementing simulated time may
actually be easier than I thought, because ReactorBase now has a
'timeout()' method that does the hard part - computing how much time there
is until the next delayed call. In earlier versions of Twisted, that logic
was buried inside something else. There are also nice new functions like
'installReactor' to play with.
So, I'm thinking I'll create a 'testreactor' module (maybe living in
osaf.framework.twisted?) with 'install()' and 'uninstall()'
functions. When installed, it'll mixin test methods into the standard
reactor, and the reactor will run on simulated time. I'm thinking that
these will probably be very simple, like a 'reset()' to completely clear
the reactor's state between tests.
I've also investigated the run()/stop() issue, and as far as I can tell
this should be a non-issue for tests that run using the Twisted default
reactor (which is what Chandler uses). The reason that you aren't supposed
to use run()/stop() or certain other functions multiple times (AFAICT), is
because certain GUI-platform-specific reactor implementations won't
tolerate it. However, tests that don't run with a GUI don't need to use a
GUI-specific reactor, and we're not using one in Chandler currently anyway.
Assuming that StringTransport is sufficient for all our simulated-socket
needs, I should only need to add a few methods. Here are the ones I have
in mind:
reactor.start() -- completely reset the reactor's state and reinitialize it
so that the current test runs with a clean slate. Also sets the reactor's
state to "running", so that the test will appear to be called from within
the reactor run loop, but in fact will have control over the reactor.
reactor.getTime() -- return the current simulated "now" moment (initially
set to the time when the test mixin is installed)
reactor.setTime(seconds) -- change the simulated "now" moment
reactor.waitFor(deferred, timeout) -- iterate until the deferred succeeds
or fails, or until the timeout occurs. Raise a TimeoutError if the timeout
happens first, or raises the deferred's exception if the deferred
fails. Otherwise, returns the deferred's value. (Note: the timeout is in
*simulated* time, not real time, so you can safely set large values if you
have a test with complex timing.)
So, I'm thinking there would also be a 'testreactor.ReactorTestCase' whose
setUp() would testreactor.install(), and reactor.start(), and whose
tearDown() would reactor.stop() (if it's still running), and perhaps
testreactor.uninstall() as well.
Then, test methods would just set up whatever conditions they want, and
then reactor.waitFor() results. Tests could safely call waitFor() multiple
times, even within the same test.
Heikki, does that sound about like what you need for your tests?
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "Dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/dev