From 4da373cb6c724eda883bfdef64b422526ed48d06 Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Tue, 4 Nov 2025 14:27:26 +0100 Subject: [PATCH] Fix flaky testItemOrder in ProgressViewTests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test was failing randomly due to a race condition with the ProgressViewerComparator's stable sorting mechanism (lastIndexes). Root cause: - The comparator maintains a HashMap of previous positions to provide visual stability (preventing jobs from jumping around in the UI) - During test execution, throttled updates would occur while jobs were being scheduled, causing some jobs to be added to lastIndexes before others - This resulted in an inconsistent baseline where jobs were sorted by schedule order rather than priority order Fix: - Reopen the progress view after all jobs are scheduled and running to reset the comparator's lastIndexes state - This ensures all jobs are sorted by priority from a clean state, eliminating the race condition - Removed the unreliable timing-based approach that tried to manipulate throttled updates The test now passes reliably by working with the stable sorting behavior rather than against it. Fixes https://github.com/eclipse-platform/eclipse.platform.ui/issues/195 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../ui/tests/progress/ProgressViewTests.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/progress/ProgressViewTests.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/progress/ProgressViewTests.java index 200bb32ea6a..520da5fb475 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/progress/ProgressViewTests.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/progress/ProgressViewTests.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; @@ -152,36 +151,49 @@ public void testItemOrder() throws Exception { // allJobs.add(keptJob); try { + // Set all jobs to not finish immediately so they stay running for comparison + for (DummyJob job : jobsToSchedule) { + job.shouldFinish = false; + } + + // Close and reopen the progress view to get a fresh comparator with empty lastIndexes + hideProgressView(); + openProgressView(); + + // Schedule all jobs in random order rapidly to minimize throttled updates between schedules ArrayList shuffledJobs = new ArrayList<>(jobsToSchedule); Collections.shuffle(shuffledJobs); StringBuilder scheduleOrder = new StringBuilder("Jobs schedule order: "); - progressView.getViewer().refresh(); // order will only hold on the first time. - Thread.sleep(200); // wait till throttled update ran. - Job dummyJob = new Job("dummy throttled caller") { - @Override - protected IStatus run(IProgressMonitor monitor) { - return Status.OK_STATUS; - } - }; - dummyJob.schedule(); // trigger throttled update to clear ProgressViewerComparator.lastIndexes - // now hope the loop is executed before next throttled update (could fail if VM - // is busy otherwise): for (DummyJob job : shuffledJobs) { - job.shouldFinish = false; - job.schedule(); // if the schedule updates the progress View (throttled) the sort order is - // affected + job.schedule(); scheduleOrder.append(job.getName()).append(", "); } TestPlugin.getDefault().getLog() .log(new Status(IStatus.OK, TestPlugin.PLUGIN_ID, scheduleOrder.toString())); + // Wait for all jobs to be running for (DummyJob job : allJobs) { processEventsUntil(() -> job.inProgress, TimeUnit.SECONDS.toMillis(3)); } - progressView.getViewer().refresh(); + + // Wait for the progress view to be updated with all jobs + processEventsUntil(() -> progressView.getViewer().getProgressInfoItems().length == allJobs.size(), + TimeUnit.SECONDS.toMillis(5)); + + // The ProgressViewerComparator uses lastIndexes for stable sorting. After throttled updates + // during job scheduling, lastIndexes may contain jobs in schedule order rather than priority order. + // Close and reopen the view again to reset the comparator's state, then do a single refresh + // to sort all jobs by priority from a clean state. + hideProgressView(); + openProgressView(); + + // Wait for the view to be populated again processEventsUntil(() -> progressView.getViewer().getProgressInfoItems().length == allJobs.size(), TimeUnit.SECONDS.toMillis(5)); + // Give time for any pending updates + processEventsUntil(() -> false, 500); + ProgressInfoItem[] progressInfoItems = progressView.getViewer().getProgressInfoItems(); assertEquals("Not all jobs visible in progress view", allJobs.size(), progressInfoItems.length); Object[] expected = allJobs.toArray();