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

Reply via email to