Skip to content

Commit

Permalink
ConsoleTests: do not wait for all Jobs
Browse files Browse the repository at this point in the history
defines a Jobfamily CONSOLE_JOB_FAMILY and only wait for that to fix
unrelated "AutoRegisterSchemeHandlersJob still running" error on MacOs
during I-Build

eclipse-platform/eclipse.platform.ui#2245
  • Loading branch information
EcljpseB0T authored and jukzi committed Sep 18, 2024
1 parent 3f34d1c commit 283f954
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.eclipse.core.internal.jobs.JobManager;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
Expand Down Expand Up @@ -177,13 +178,14 @@ public static boolean waitWhile(Supplier<Boolean> condition, long timeout) throw
*
* @param owner name of the caller which will be logged as prefix if the
* wait times out
* @param jobFamily the jobFamily to wait for
* @param minTimeMs minimum wait time in milliseconds
* @param maxTimeMs maximum wait time in milliseconds
* @return true if the method timed out, false if all the jobs terminated
* before the timeout
*/
public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs) {
return waitForJobs(owner, minTimeMs, maxTimeMs, (Object[]) null);
public static boolean waitForJobs(String owner, Object jobFamily, long minTimeMs, long maxTimeMs) {
return waitForJobs(owner, jobFamily, minTimeMs, maxTimeMs, (Object[]) null);
}

/**
Expand All @@ -202,11 +204,16 @@ public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs)
* @return true if the method timed out, false if all the jobs terminated before the timeout
*/
public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs, Object... excludedFamilies) {
return waitForJobs(owner, null, minTimeMs, maxTimeMs, excludedFamilies);
}

public static boolean waitForJobs(String owner, Object jobFamily, long minTimeMs, long maxTimeMs, Object... excludedFamilies) {
if (maxTimeMs < minTimeMs) {
throw new IllegalArgumentException("Max time is smaller as min time!");
}
final long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < minTimeMs) {
Job.getJobManager().wakeUp(jobFamily);
final long start = System.nanoTime();
while (System.nanoTime() - start < minTimeMs * 1_000_000) {
processUIEvents();
try {
Thread.sleep(Math.min(10, minTimeMs));
Expand All @@ -215,7 +222,7 @@ public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs,
}
}
while (!Job.getJobManager().isIdle()) {
List<Job> jobs = getRunningOrWaitingJobs(null, excludedFamilies);
List<Job> jobs = getRunningOrWaitingJobs(jobFamily, excludedFamilies);
if (jobs.isEmpty()) {
// only uninteresting jobs running
break;
Expand All @@ -229,7 +236,7 @@ public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs,
return true;
}

if (System.currentTimeMillis() - start >= maxTimeMs) {
if (System.nanoTime() - start >= maxTimeMs * 1_000_000) {
dumpRunningOrWaitingJobs(owner, jobs);
return true;
}
Expand All @@ -239,15 +246,14 @@ public static boolean waitForJobs(String owner, long minTimeMs, long maxTimeMs,
runningJobs.clear();
return false;
}

static Set<Job> runningJobs = new LinkedHashSet<>();

private static void dumpRunningOrWaitingJobs(String owner, List<Job> jobs) {
String message = "Some job is still running or waiting to run: " + dumpRunningOrWaitingJobs(jobs);
String message = "Some job is still running or waiting to run: " + getDump(jobs);
log(IStatus.ERROR, owner, message, new RuntimeException(message));
}

private static String dumpRunningOrWaitingJobs(List<Job> jobs) {
private static String getDump(List<Job> jobs) {
if (jobs.isEmpty()) {
return "";
}
Expand All @@ -258,6 +264,7 @@ private static String dumpRunningOrWaitingJobs(List<Job> jobs) {
runningJobs.add(job);
sb.append("\n'").append(job.toString()).append("'/");
sb.append(job.getClass().getName());
sb.append(":").append(JobManager.printState(job));
Thread thread = job.getThread();
if (thread != null) {
ThreadInfo[] threadInfos = ManagementFactory.getThreadMXBean().getThreadInfo(new long[] { thread.getId() }, true, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.internal.console.ConsoleManager;
import org.eclipse.ui.part.IPageBookViewPage;
import org.eclipse.ui.part.MessagePage;
import org.junit.After;
Expand Down Expand Up @@ -85,7 +86,7 @@ public void setUp() throws Exception {
firstConsole = new ConsoleMock(0);
manager.addConsoles(new ConsoleMock[] { firstConsole });
manager.showConsoleView(firstConsole);
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
TestUtil.processUIEvents(100);
ConsoleMock.allShownConsoles.set(0);
}
Expand Down Expand Up @@ -118,7 +119,7 @@ public void testShowAllConsoles() throws Exception {

// Console manager starts a job with delay, let wait for him a bit
System.out.println("Waiting on jobs now..."); //$NON-NLS-1$
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);

// Give UI a chance to proceed pending console manager jobs
System.out.println("Done with jobs, processing UI events again..."); //$NON-NLS-1$
Expand Down Expand Up @@ -161,7 +162,7 @@ private void showConsole(final ConsoleMock console) {
latch.await(1, TimeUnit.MINUTES);
System.out.println("Requesting to show: " + console); //$NON-NLS-1$
manager.showConsoleView(console);
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.interrupted();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.internal.console.ConsoleManager;
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
import org.junit.Test;

Expand All @@ -55,21 +56,21 @@ public void testConsoleOutputStreamEncoding() throws IOException {
MessageConsole console = new MessageConsole("Test Console", //$NON-NLS-1$
IConsoleConstants.MESSAGE_CONSOLE_TYPE, null, StandardCharsets.UTF_8.name(), true);
IDocument document = console.getDocument();
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
assertEquals("Document should be empty", "", document.get()); //$NON-NLS-1$ //$NON-NLS-2$
try (IOConsoleOutputStream outStream = console.newOutputStream()) {
outStream.write(testStringBuffer, 0, 6);
// half of ö (\u00f6) is written so we don't expect this char in
// output but all previous chars can be decoded
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
assertEquals("First 4 chars should be written", testString.substring(0, 4), document.get()); //$NON-NLS-1$
outStream.write(testStringBuffer, 6, 6);
// all remaining bytes are written so we expect the whole string
// including the ö (\u00f6) which was at buffer boundary
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
assertEquals("whole test string should be written", testString, document.get()); //$NON-NLS-1$
}
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
// after closing the stream, the document content should still be the
// same
assertEquals("closing the stream should not alter the document", testString, document.get()); //$NON-NLS-1$
Expand All @@ -83,15 +84,15 @@ public void testConsoleOutputStreamLastR() throws IOException {
MessageConsole console = new MessageConsole("Test Console 2", //$NON-NLS-1$
IConsoleConstants.MESSAGE_CONSOLE_TYPE, null, StandardCharsets.UTF_8.name(), true);
IDocument document = console.getDocument();
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
assertEquals("Document should be empty", "", document.get()); //$NON-NLS-1$ //$NON-NLS-2$
try (IOConsoleOutputStream outStream = console.newOutputStream()) {
outStream.write(testStringBuffer);
// everything but pending \r should be written
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
assertEquals("First char should be written", testString.substring(0, 1), document.get()); //$NON-NLS-1$
}
TestUtil.waitForJobs(name.getMethodName(), 200, 5000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 200, 5000);
// after closing the stream, the document content should still be the
// same
assertEquals("closing the stream should write the pending \\r", testString, document.get()); //$NON-NLS-1$
Expand Down Expand Up @@ -182,7 +183,7 @@ public void testFindCommandsAreEnabledOnConsoleOpen() throws Exception {
try {
consoleManager.addConsoles(consoles);
consoleManager.showConsoleView(console);
TestUtil.waitForJobs(name.getMethodName(), 100, 3000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 100, 3000);

ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
Command commandFindReplace = commandService.getCommand(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.eclipse.debug.tests.console;

import org.eclipse.debug.tests.TestUtil;
import org.eclipse.ui.internal.console.ConsoleManager;

/**
* Same as {@link IOConsoleTests} but with fixed width console enabled.
Expand All @@ -29,7 +30,7 @@ protected IOConsoleTestUtil getTestUtil(String title) {
c.getConsole().setConsoleWidth(3);
c.setIgnoreFixedConsole(true);
// console width is applied asynchronous
TestUtil.waitForJobs(name.getMethodName(), 50, 1000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 50, 1000);
return c;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.internal.ui.views.console.ProcessConsoleManager;
import org.eclipse.debug.tests.TestUtil;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
Expand All @@ -41,6 +42,7 @@
import org.eclipse.ui.console.IConsoleDocumentPartitioner;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.internal.console.ConsoleManager;

/**
* Utility to help testing input and output in {@link IOConsole}.
Expand Down Expand Up @@ -237,7 +239,7 @@ public IOConsoleTestUtil insert(String content) {
// content the caret is updated
setCaretOffset(e.start + content.length());
}
TestUtil.waitForJobs(name, 0, 1000);
TestUtil.waitForJobs(name, ConsoleManager.CONSOLE_JOB_FAMILY, 0, 1000);
return this;
}

Expand Down Expand Up @@ -288,7 +290,7 @@ public IOConsoleTestUtil insertTyping(String content) {
textPanel.notifyListeners(SWT.KeyDown, e);
textPanel.notifyListeners(SWT.KeyUp, e);
}
TestUtil.waitForJobs(name, 0, 1000);
TestUtil.waitForJobs(name, ConsoleManager.CONSOLE_JOB_FAMILY, 0, 1000);
return this;
}

Expand Down Expand Up @@ -693,7 +695,8 @@ public IOConsoleTestUtil verifyPartitions(final int offset, final int length, fi
* @return this {@link IOConsoleTestUtil} to chain methods
*/
public IOConsoleTestUtil waitForScheduledJobs() {
TestUtil.waitForJobs(name, 25, 5 * 2000);
TestUtil.waitForJobs(name, ProcessConsoleManager.class, 25, 5 * 2000);
TestUtil.waitForJobs(name, ConsoleManager.CONSOLE_JOB_FAMILY, 25, 5 * 2000);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.internal.console.ConsoleManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -162,7 +163,7 @@ protected IOConsoleTestUtil getTestUtil(String title) {
});
final IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
consoleManager.addConsoles(new IConsole[] { console });
TestUtil.waitForJobs(name.getMethodName(), 25, 10000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 25, 10000);
consoleManager.showConsoleView(console);
@SuppressWarnings("restriction")
final org.eclipse.ui.internal.console.IOConsolePage page = (org.eclipse.ui.internal.console.IOConsolePage) consoleView.getCurrentPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ public void testProcessConsoleLifecycle() throws Exception {
launch = process.getLaunch();
launchManager.addLaunch(launch);
// do not wait on input read job
TestUtil.waitForJobs(name.getMethodName(), 0, 10000, ProcessConsole.class);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsoleManager.class, 0, 10000, ProcessConsole.class);
assertThat(consoleManager.getConsoles()).as("console has been added").hasSize(1);
} finally {
mockProcess.destroy();
}

if (launch != null) {
launchManager.removeLaunch(launch);
TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsoleManager.class, 0, 10000);
assertThat(consoleManager.getConsoles()).as("console has been removed").isEmpty();
}
}
Expand All @@ -106,15 +106,15 @@ public void testBug546710_ConsoleCreationRaceCondition() throws Exception {
setPreference(DebugUIPlugin.getDefault().getPreferenceStore(), IDebugUIConstants.PREF_AUTO_REMOVE_OLD_LAUNCHES, true);
// Stop the JobManager to reliable trigger the tested race
// condition.
TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsoleManager.class, 0, 10000);
Job.getJobManager().suspend();
launchManager.addLaunch(process1.getLaunch());
launchManager.addLaunch(process2.getLaunch());
} finally {
Job.getJobManager().resume();
}

TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsoleManager.class, 0, 10000);
ProcessConsoleManager processConsoleManager = DebugUIPlugin.getDefault().getProcessConsoleManager();
ILaunch[] launches = launchManager.getLaunches();
Set<IConsole> openConsoles = new HashSet<>();
Expand All @@ -135,7 +135,7 @@ public void testBug546710_ConsoleCreationRaceCondition() throws Exception {
assertThat(removeAction).matches(ConsoleRemoveAllTerminatedAction::isEnabled, "is enabled");
}
removeAction.run();
TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsoleManager.class, 0, 10000);
assertNull("First console not removed.", processConsoleManager.getConsole(process1));
assertNull("Second console not removed.", processConsoleManager.getConsole(process1));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
import org.eclipse.debug.tests.AbstractDebugTest;
import org.eclipse.debug.tests.TestUtil;
import org.eclipse.debug.tests.launching.LaunchConfigurationTests;
Expand All @@ -67,6 +68,7 @@
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.eclipse.ui.internal.console.ConsoleManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -229,7 +231,7 @@ public void testInputReadJobCancel() throws Exception {
final Class<?> jobFamily = org.eclipse.debug.internal.ui.views.console.ProcessConsole.class;
assertThat(Job.getJobManager().find(jobFamily)).as("check input read job started").hasSizeGreaterThan(0);
Job.getJobManager().cancel(jobFamily);
TestUtil.waitForJobs(name.getMethodName(), 0, 1000);
TestUtil.waitForJobs(name.getMethodName(), ProcessConsole.class, 0, 1000);
assertThat(Job.getJobManager().find(jobFamily)).as("check input read job is canceled").isEmpty();
} finally {
console.destroy();
Expand Down Expand Up @@ -301,7 +303,7 @@ public void processTerminationTest(ILaunchConfiguration launchConfig, boolean te
waitWhile(__ -> !terminationSignaled.get(), 10_000, __ -> "No console complete notification received.");
} finally {
consoleManager.removeConsoles(new IConsole[] { console });
TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 0, 10000);
}
}

Expand Down Expand Up @@ -422,7 +424,7 @@ private IOConsole doConsoleOutputTest(byte[] testContent, Map<String, Object> la
process.terminate();
}
consoleManager.removeConsoles(new IConsole[] { console });
TestUtil.waitForJobs(name.getMethodName(), 0, 1000);
TestUtil.waitForJobs(name.getMethodName(), ConsoleManager.CONSOLE_JOB_FAMILY, 0, 1000);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
* @since 3.0
*/
public class ConsoleManager implements IConsoleManager {
public static final String CONSOLE_JOB_FAMILY = "CONSOLE_JOB_FAMILY"; //$NON-NLS-1$

/**
* Console listeners
Expand Down Expand Up @@ -93,6 +94,11 @@ public RepaintJob() {
setSystem(true);
}

@Override
public boolean belongsTo(Object family) {
return family == ConsoleManager.CONSOLE_JOB_FAMILY;
}

void addConsole(IConsole console) {
synchronized (list) {
list.add(console);
Expand Down Expand Up @@ -260,6 +266,11 @@ private class ShowConsoleViewJob extends WorkbenchJob {
setPriority(Job.SHORT);
}

@Override
public boolean belongsTo(Object family) {
return family == ConsoleManager.CONSOLE_JOB_FAMILY;
}

void addConsole(IConsole console) {
synchronized (queue) {
queue.add(console);
Expand Down Expand Up @@ -359,6 +370,11 @@ public void warnOfContentChange(final IConsole console) {
if (!fWarnQueued) {
fWarnQueued = true;
Job job = new UIJob(ConsolePlugin.getStandardDisplay(), ConsoleMessages.ConsoleManager_consoleContentChangeJob) {
@Override
public boolean belongsTo(Object family) {
return family == ConsoleManager.CONSOLE_JOB_FAMILY;
}

@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
Expand Down
Loading

0 comments on commit 283f954

Please sign in to comment.