From 618108256b21fc966d9abb8b56d566c3c9a57907 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Sun, 2 Mar 2025 18:52:55 +0100 Subject: [PATCH] fix #572: TestNG view may miss results The TestNG view in Eclipse could be incomplete and show the wrong status if tests were executed faster than the UI updates. The reason was that the listener receiving the TestResultMessages updated the UI synchronously. Once the test finished the UI update would stop. Unprocessed test results were dropped. Fixed by queueing all synchronous UI updates and executing them in the order they arrived. --- .../testng/eclipse/ui/TestRunnerViewPart.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/testng-eclipse-plugin/src/main/org/testng/eclipse/ui/TestRunnerViewPart.java b/testng-eclipse-plugin/src/main/org/testng/eclipse/ui/TestRunnerViewPart.java index 0b4946ac..b8c3da00 100644 --- a/testng-eclipse-plugin/src/main/org/testng/eclipse/ui/TestRunnerViewPart.java +++ b/testng-eclipse-plugin/src/main/org/testng/eclipse/ui/TestRunnerViewPart.java @@ -8,6 +8,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; @@ -209,6 +211,30 @@ public class TestRunnerViewPart extends ViewPart // MAX_TEXT_SIZE_THRESHOLD. private static final int MAX_RESULTS_THRESHOLD = 1000; private static final int MAX_TEXT_SIZE_THRESHOLD = 3; + + private static final BlockingQueue SYNC_RUNNABLE_QUEUE = new LinkedBlockingDeque<>(); + + static { + Thread t = new Thread() { + @Override + public void run() { + while (true) { + try { + Runnable runnable = SYNC_RUNNABLE_QUEUE.take(); + runnable.run(); + } catch (InterruptedException ex) { + TestNGPlugin.log(ex); + break; + } catch (RuntimeException ex) { + TestNGPlugin.log(ex); + } + } + } + }; + t.setName("testng-sync-runnable-executor"); //$NON-NLS-1$ + t.setDaemon(true); + t.start(); + } /** Infos for the current suite run. */ private SuiteRunInfo currentSuiteRunInfo; @@ -584,9 +610,11 @@ public synchronized void dispose() { } private void postSyncRunnable(Runnable r) { - if(!isDisposed()) { - getDisplay().syncExec(r); - } + SYNC_RUNNABLE_QUEUE.add(() -> { + if(!isDisposed()) { + getDisplay().syncExec(r); + } + }); } private void postAsyncRunnable(Runnable r) {