Skip to content

Commit dd5d18e

Browse files
vogellaclaude
andcommitted
Fix flaky DynamicTest.testDynamicRegistry race condition
The testDynamicRegistry test was failing randomly with "Activity Listener not called" or "Category Listener not called" errors. Root cause: - The test uses a plain boolean array to track listener invocations - Extension registry listeners may be invoked on different threads - Without proper synchronization (volatile/atomic), changes to the array made by listener threads may not be visible to the test thread - This causes DisplayHelper.waitForCondition() to timeout even when listeners were actually called Fix: - Replace boolean[] with AtomicBoolean instances for thread-safe visibility - Use activityChanged.set(true) and categoryChanged.set(true) in listeners - Use activityChanged.get() and categoryChanged.get() in assertions - AtomicBoolean provides proper memory barriers ensuring cross-thread visibility This approach ensures proper synchronization between the listener callback threads and the test thread, eliminating the race condition that caused random test failures. Fixes #2458 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a2174ff commit dd5d18e

File tree

1 file changed

+8
-6
lines changed
  • tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/activities

1 file changed

+8
-6
lines changed

tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/activities/DynamicTest.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.nio.charset.StandardCharsets;
2424
import java.util.HashSet;
2525
import java.util.Set;
26+
import java.util.concurrent.atomic.AtomicBoolean;
2627

2728
import org.eclipse.core.internal.registry.ExtensionRegistry;
2829
import org.eclipse.core.runtime.ContributorFactoryOSGi;
@@ -412,14 +413,15 @@ public void testDynamicRegistry() throws NotDefinedException {
412413
assertFalse(category.isDefined());
413414
// set to true when the activity/category in question have had an event
414415
// fired
415-
final boolean[] registryChanged = new boolean[] { false, false };
416+
final AtomicBoolean activityChanged = new AtomicBoolean(false);
417+
final AtomicBoolean categoryChanged = new AtomicBoolean(false);
416418
activity.addActivityListener(activityEvent -> {
417419
System.err.println("activityChanged");
418-
registryChanged[0] = true;
420+
activityChanged.set(true);
419421
});
420422
category.addCategoryListener(categoryEvent -> {
421423
System.err.println("categoryChanged");
422-
registryChanged[1] = true;
424+
categoryChanged.set(true);
423425

424426
});
425427

@@ -442,10 +444,10 @@ public void testDynamicRegistry() throws NotDefinedException {
442444
// spin the event loop and ensure that the changes come down the pipe.
443445
// 20 seconds should be more than enough
444446
DisplayHelper.waitForCondition(PlatformUI.getWorkbench().getDisplay(), 20000,
445-
() -> registryChanged[0] && registryChanged[1]);
447+
() -> activityChanged.get() && categoryChanged.get());
446448

447-
assertTrue("Activity Listener not called", registryChanged[0]);
448-
assertTrue("Category Listener not called", registryChanged[1]);
449+
assertTrue("Activity Listener not called", activityChanged.get());
450+
assertTrue("Category Listener not called", categoryChanged.get());
449451

450452
assertTrue(activity.isDefined());
451453
Set<IActivityPatternBinding> patternBindings = activity.getActivityPatternBindings();

0 commit comments

Comments
 (0)