From 4f71f7aed3c828aa3f0c3e57bb1a8be5d033a62e Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Fri, 7 Nov 2025 13:06:02 +0100 Subject: [PATCH] Fix flaky DecoratorAdaptableTests by waiting for decorator jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous fix in commit 9c171a0411 added UITestUtil.processEvents() to wait for decorator enablement, but this only processes the event queue and doesn't wait for asynchronous jobs to complete. The DecoratorManager.setEnabled() method triggers updateForEnablementChange() which uses fireListenersInUIThread() to schedule WorkbenchJob instances. These jobs may not complete before tests check decoration results, causing intermittent failures. This fix introduces waitForDecoratorJobs() which uses Job.getJobManager().join() to wait for all FAMILY_DECORATE jobs to complete before proceeding with tests. Fixes: https://github.com/eclipse-platform/eclipse.platform.ui/issues/868 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../decorators/DecoratorAdaptableTests.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/decorators/DecoratorAdaptableTests.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/decorators/DecoratorAdaptableTests.java index ec10a7a93ce..b9e5faad119 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/decorators/DecoratorAdaptableTests.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/decorators/DecoratorAdaptableTests.java @@ -20,6 +20,7 @@ import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.decorators.DecorationResult; @@ -44,6 +45,21 @@ private String getDecorationTextFor(Object object) { return result.decorateWithText("Default label"); } + /** + * Waits for all decorator-related jobs to complete. + * This ensures that decorator enablement changes have been fully processed + * before tests check decoration results. + */ + private void waitForDecoratorJobs() { + try { + Job.getJobManager().join(DecoratorManager.FAMILY_DECORATE, null); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + // Also process any pending UI events + UITestUtil.processEvents(); + } + private void assertDecorated(String testSubName, String[] expectedSuffixes, Object[] elements, boolean shouldHaveMatches) { for (Object object : elements) { @@ -65,9 +81,9 @@ public void doSetUp() throws Exception { PlatformUI.getWorkbench().getDecoratorManager().setEnabled(TestResourceDecoratorContributor.ID, true); PlatformUI.getWorkbench().getDecoratorManager().setEnabled(TestResourceMappingDecoratorContributor.ID, true); - // Process all pending UI events to ensure decorator enablement has completed - // This prevents race conditions where decorators may not be fully registered yet - UITestUtil.processEvents(); + // Wait for all decorator jobs to complete after enabling decorators + // This prevents race conditions where decorators may not be fully initialized yet + waitForDecoratorJobs(); } @After @@ -77,8 +93,8 @@ public void doTearDown() throws Exception { PlatformUI.getWorkbench().getDecoratorManager().setEnabled(TestResourceDecoratorContributor.ID, false); PlatformUI.getWorkbench().getDecoratorManager().setEnabled(TestResourceMappingDecoratorContributor.ID, false); - // Process all pending UI events to ensure clean state for next test - UITestUtil.processEvents(); + // Wait for all decorator jobs to complete to ensure clean state for next test + waitForDecoratorJobs(); } /**