Hi all
When I run my unit tests which among others, consists of 2 TestCase subclass that makes connections to a server socket. I get a green light for all the unit tests however when the tests ends (or when the 2nd TestCase subclass in question runs) I see a walkback below. I'm still having problem reducing it to a self contained unit test package, although I can reproduce it everytime. In the meantime, does the error suggest anything to anyone? Thanks. '#onAsyncAccept is the responsibility of the subclass' Socket(Object)>>subclassResponsibility Socket(SocketAbstract)>>onAsyncAccept WinAsyncSocket>>wsaEvent:wParam:lParam: WinAsyncSocket(View)>>dispatchUser:wParam:lParam:map: WinAsyncSocket>>dispatchUser:wParam:lParam: WinAsyncSocket(View)>>dispatchMessage:wParam:lParam: [] in InputState>>wndProc:message:wParam:lParam:cookie: BlockClosure>>ifCurtailed: ProcessorScheduler>>callback:evaluate: InputState>>wndProc:message:wParam:lParam:cookie: InputState>>pumpMessage: InputState>>loopWhile: InputState>>mainLoop [] in InputState>>forkMain ExceptionHandler(ExceptionHandlerAbstract)>>markAndTry [] in ExceptionHandler(ExceptionHandlerAbstract)>>try: BlockClosure>>ifCurtailed: BlockClosure>>ensure: ExceptionHandler(ExceptionHandlerAbstract)>>try: BlockClosure>>on:do: [] in BlockClosure>>newProcess Hwee Boon |
Yar Hwee Boon wrote:
> When I run my unit tests which among others, consists of 2 TestCase > subclass that makes connections to a server socket. I get a green > light for all the unit tests however when the tests ends (or when the > 2nd TestCase subclass in question runs) I see a walkback below. I'm > still having problem reducing it to a self contained unit test > package, although I can reproduce it everytime. In the meantime, does > the error suggest anything to anyone? Thanks. You're in luck! I ran into the same sort of problem just this past week and figured out what was going on. Scenario was that individual tests would run fine. But running batches of tests would produce errors like you see. The main problem I was getting was a 'Remote Socket closed' exception in ServerSocket>>accept. Another would be to get a #subclassResponsibility error when #onAsyncRead (which is implemented by Socket) was sent to a ServerSocket. Here's how the errors can arise. Dolphin 5 uses the asynchronous socket interface, where events about socket activity come through the windows message queue. WinAsyncSocket uses the Socket descriptor to match up a windows message to the appropriate socket. However, a socket descriptor may be reused by Windows after it's been closed. So imagine this sequence: a test uses a socket (let's call it A). The test finishes but happens to leave some socket related message in the windows message queue (which was destined for socket A). The test closes the socket. The running process immediately moves onto the next testCase. It also creates a socket (call it B). Windows happens to reuse the same descriptor for B that had been used for A. Now when the main UI process gets a chance to run, it gets the socket message (destined for A), but sends it to the current socket with that descriptor (which is B). Messages meant only for Socket can go to ServerSocket, and vise-versa. Basically the fix is to make sure the windows message queue gets processed. Probably by putting something in #tearDown after closing any sockets used by the test. One way might be to put in "SessionManager inputState pumpMessages". I ended up using the #waitForUIProcessToIdle method that I added some time ago to assist with unit testing of the user interface. It actually waits until all normal priority processes have idled by seeing when a #userBackgroundPriority process gets a chance to run. If called from the main UI process, it uses a ModalMsgLoop which processes the windows message queue. If called from other than the main UI process, it simply waits on a Semaphore, which gives the main UI process a chance to run which will process the windows message queue. hope this helps, -Bill ----------------------- waitForUIProcessToIdle "General hack to simulate the idling of the system so that testCases can proceed once everything in the UI process has been taken care of." | waitLoop | waitLoop := Processor isActiveMain ifTrue: [ModalMsgLoop new] ifFalse: [Semaphore new]. [waitLoop signal. SessionManager inputState prod] forkAt: Processor userBackgroundPriority. waitLoop wait! ! ------------------------------------------- Bill Dargel [hidden email] Shoshana Technologies 100 West Joy Road, Ann Arbor, MI 48105 USA |
Bill Dargel <[hidden email]> wrote in message news:<[hidden email]>...
> You're in luck! I ran into the same sort of problem just this past week I absolutely agree. > So imagine this sequence: a test uses a socket (let's call it A). The > test finishes but happens to leave some socket related message in the > windows message queue (which was destined for socket A). The test closes > the socket. The running process immediately moves onto the next > testCase. It also creates a socket (call it B). Windows happens to reuse > the same descriptor for B that had been used for A. Now when the main UI > process gets a chance to run, it gets the socket message (destined for > A), but sends it to the current socket with that descriptor (which is > B). Thanks, your explanation made the problem clear. Just a thought, wouldn't a Dolphin Smalltalk program that allows many socket connections be at high risk to this problem? It sounds like a bug.. > processed. Probably by putting something in #tearDown after closing any > sockets used by the test. One way might be to put in "SessionManager > inputState pumpMessages". I tried exactly that, and the problem went away. > > I ended up using the #waitForUIProcessToIdle method that I added some > time ago to assist with unit testing of the user interface. When would you need to use this instead of "SessionManager inputState pumpMessages"? > hope this helps, Of course, thanks!! And sorry for the additional questions :) Hwee Boon |
Yar Hwee Boon wrote:
> Thanks, your explanation made the problem clear. Just a thought, > wouldn't a Dolphin Smalltalk program that allows many socket > connections be at high risk to this problem? It sounds like a bug.. It's obviously a potential problem. And it certainly could have figured into Andy and Blair's thinking when they redid the socket implementation in Dolphin 6 to use overlapped calls on a synchronous interface. Earlier this week, while fighting this problem, I was wishing that D6 wasn't quite so far away. But, that being said, it might not be a problem for a "typical" application. (given the caveat that what someone considers typical can vary quite a bit). To keep a program responsive, the main UI process needs to be regularly free to handle incoming messages. The architecture that does that, will also be keeping the sockets happy. I've found that running batches of unit (and more so acceptance) tests can easily stress things more, by starving the processing of the windows message queue, compared to the interactive program that's being tested. > > I ended up using the #waitForUIProcessToIdle method that I added some > > time ago to assist with unit testing of the user interface. > > When would you need to use this instead of "SessionManager inputState > pumpMessages"? I guess for this situation, there isn't a difference. I had used #waitForUIProcessToIdle just because it's a fix I tend to reach for when I have a testCase that needs further synchronization with the main UI process. I've had situations where an expected result won't be there for a test to check, until after a co-process or background process has had a chance to run. This method has just been an easy to use, generic, way to deal with that, without the testCase having to know about or hook into some more specific means of synchronization. <grin>One way that I'll realize that it's needed, is when the assert of a test that failed, passes by the time I look at it in the debugger.</grin> -Bill ------------------------------------------- Bill Dargel [hidden email] Shoshana Technologies 100 West Joy Road, Ann Arbor, MI 48105 USA |
Free forum by Nabble | Edit this page |