Summary: | RSEInternalFrameworkTestCase.testWaitAndDispatch() fails on my machine | ||||||
---|---|---|---|---|---|---|---|
Product: | [Tools] Target Management | Reporter: | Martin Oberhuber <mober.at+eclipse> | ||||
Component: | RSE | Assignee: | Martin Oberhuber <mober.at+eclipse> | ||||
Status: | RESOLVED FIXED | QA Contact: | Martin Oberhuber <mober.at+eclipse> | ||||
Severity: | normal | ||||||
Priority: | P3 | CC: | uwe.st | ||||
Version: | 3.0 | ||||||
Target Milestone: | 3.0 M5 | ||||||
Hardware: | PC | ||||||
OS: | Windows XP | ||||||
Whiteboard: | |||||||
Bug Depends on: | |||||||
Bug Blocks: | 219101, 219069, 219111 | ||||||
Attachments: |
|
Description
Martin Oberhuber
2008-02-15 08:06:47 EST
It turns out the problem is, that SystemView.moveTreeItems() is passed "null" items in the following traceback. The question is, why the SystemView$ResourceChangedJob only runs from inside the RSEWaitAndDispatchUtil.waitAndDispatch(). It looks like this ResourceChangedJob really belongs to a different test, and that test is not fully finished / cleaned up before the event loop test is done. Anyways, such a situation can occur in an RSE application as well. Something happens to RSE, and the ResourceChangedJob is allowed only to run a lot later (after the resources in question have gone already). Need to investigate how such access to deleted resources can be avoided. Thread [main] (Suspended (breakpoint at line 1505 in SystemView)) SystemView.moveTreeItem(Widget, Item, Object, int) line: 1505 SystemView.moveTreeItems(Widget, Object[], int) line: 1554 SystemView$ResourceChangedJob.runInUIThread(IProgressMonitor) line: 2292 UIJob$1.run() line: 94 RunnableLock.run() line: 35 UISynchronizer(Synchronizer).runAsyncMessages(boolean) line: 130 Display.runAsyncMessages(boolean) line: 3737 Display.readAndDispatch() line: 3374 RSEWaitAndDispatchUtil.waitAndDispatch(long) line: 62 RSEInternalFrameworkTestCase.testWaitAndDispatch() line: 110 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object[]) line: 324 RSEInternalFrameworkTestCase(TestCase).runTest() line: 164 RSEInternalFrameworkTestCase(RSECoreTestCase).runTest() line: 308 RSEInternalFrameworkTestCase(TestCase).runBare() line: 130 RSEInternalFrameworkTestCase(RSECoreTestCase).runBare() line: 294 TestResult$1.protect() line: 106 TestResult.runProtected(Test, Protectable) line: 124 TestResult.run(TestCase) line: 109 RSEInternalFrameworkTestCase(TestCase).run(TestResult) line: 120 RSEInternalFrameworkTestCase(RSECoreTestCase).run(TestResult) line: 263 TestSuite.runTest(Test, TestResult) line: 230 [...] The "old" ResourceChangedJob comes from FireNewHostEvents... and these, in turn, come from the (1) InitRSEJob, (2) HostMoveTest. (3) RSEConnectionTestCase.testConnectionCreation() The point is that in case of (2) and (3), these test cases run on the main thread, but events are ALWAYS fired with Display.getDefault().asyncExec() in the SystemRegistry. Since the tests are on the main thread, the event loop is never emptied and RSE has no chance handling all these events... they fill up the event queue but the events don't get executed. So when HostMoveTest#tearDown() is executed, the events are still in the event queue. Now, hosts are deleted. When the eventQueue finally gets a chance to be emptied (through our testWaitAndDispatch() test, the events are finally run - but the corresponding hosts do not exist any more in the SystemRegistry. It looks like what we need to do is (a) In FireNewHostEvents, ensure that the corresponding host still exists when the event(s) are fired. There is no use in notifying about a new host when the host has been deleted again in the meantime. The impact of the change can only be for programs that add and remove hosts very quickly on the dispatch thread. Because an interactive user would need to work on the dispatch thread, so events would get a chance to get executed. (b) Investigate whether we should really do Display.asyncExec() in the SystemRegistry.createHost() in the case where we are already on the display thread. Perhaps it's wiser to fire the event right away. Though the risk with this is, that event listeners destabilize the system... we've seen this in the past. (c) In the test case, since we're running on the main thread, we'll need to wait until the system has stabilized before stepping on to the next test. This is necessary because unit tests should always be isolated from each other. SystemRegistry.createHost(String, IRSESystemType, String, String, String, String, int, boolean, ISystemNewConnectionWizardPage[]) line: 1654 SystemRegistry.createHost(String, IRSESystemType, String, String, String, String, int, ISystemNewConnectionWizardPage[]) line: 1543 RSEConnectionManager.findOrCreateConnection(IRSEConnectionProperties) line: 234 HostMoveTest.createHosts() line: 151 HostMoveTest.setUp() line: 42 HostMoveTest(TestCase).runBare() line: 128 HostMoveTest(RSECoreTestCase).runBare() line: 294 TestResult$1.protect() line: 106 TestResult.runProtected(Test, Protectable) line: 124 TestResult.run(TestCase) line: 109 HostMoveTest(TestCase).run(TestResult) line: 120 HostMoveTest(RSECoreTestCase).run(TestResult) line: 263 TestSuite.runTest(Test, TestResult) line: 230 TestSuite.run(TestResult) line: 225 Created attachment 89848 [details]
Patch fixing the problem
Attached patch fixes the concrete problem with testWaitAndDispatch(), by shielding tests from each other. This is done by adding a
flushEventQueue();
method in the RSEBaseTestCase, and calling it from the tearDown() method.
Patch committed: [219086] flush event queue to shield tests from each other Fixing the immediate issue surfaced problems in other areas of RSE. These are tracked separately by bug 219101, bug 219069 and bug 219111. |