diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/SwtLeakTestWatcher.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/SwtLeakTestWatcher.java new file mode 100644 index 00000000000..dd9e42bb9fc --- /dev/null +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/SwtLeakTestWatcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2000, 2023 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.tests; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.junit.Assert; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +public class SwtLeakTestWatcher extends TestWatcher { + + IWorkbench workbench; + Set preExistingShells; + + @Override + protected void starting(Description description) { + workbench = PlatformUI.getWorkbench(); + preExistingShells = Set.of(workbench.getDisplay().getShells()); + super.starting(description); + } + + @Override + protected void finished(Description description) { + // Check for shell leak. + List leakedModalShellTitles = new ArrayList<>(); + Shell[] shells = workbench.getDisplay().getShells(); + for (Shell shell : shells) { + if (!shell.isDisposed() && !preExistingShells.contains(shell)) { + leakedModalShellTitles.add(shell.getText()); + // closing shell may introduce "not disposed" errors in next tests : + // shell.close(); + } + } + if (!leakedModalShellTitles.isEmpty()) { + Assert.fail(description.getClassName() + "." + description.getDisplayName() + + " Test leaked modal shell(s): [" + String.join(", ", leakedModalShellTitles) + "]"); + } + super.finished(description); + } + +} \ No newline at end of file diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/NestedSyncExecDeadlockTest.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/NestedSyncExecDeadlockTest.java index 4767d79cfef..7e5b65c3550 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/NestedSyncExecDeadlockTest.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/NestedSyncExecDeadlockTest.java @@ -29,9 +29,12 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; /** * This is a regression test for a case where a recursive attempt to syncExec @@ -39,6 +42,9 @@ */ public class NestedSyncExecDeadlockTest { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + private static class ResourceListener implements IResourceChangeListener { @Override public void resourceChanged(IResourceChangeEvent event) { @@ -53,7 +59,8 @@ public void resourceChanged(IResourceChangeEvent event) { private final IWorkspace workspace = ResourcesPlugin.getWorkspace(); public void doTest(final long timeToSleep) throws Exception { - ProgressMonitorDialog dialog = new ProgressMonitorDialog(new Shell()); + Shell shell = new Shell(); + ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); dialog.run(true, false, new WorkspaceModifyOperation() { @Override public void execute(final IProgressMonitor pm) { @@ -77,6 +84,7 @@ public void execute(final IProgressMonitor pm) { }); } }); + shell.close(); } @Before diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug108162.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug108162.java index cbbc4b14706..199b23ea8d4 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug108162.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug108162.java @@ -26,7 +26,10 @@ import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.tests.SwtLeakTestWatcher; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; /** * Tests the following sequence of events: @@ -38,6 +41,10 @@ * This test asserts that the exception is thrown and that deadlock does not occur. */ public class TestBug108162 { + + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + static class LockAcquiringOperation extends WorkspaceModifyOperation { @Override public void execute(final IProgressMonitor pm) { @@ -52,8 +59,9 @@ public void execute(final IProgressMonitor pm) { */ @Test public void testBug() throws CoreException { + Shell shell = new Shell(); workspace.run((IWorkspaceRunnable) monitor -> { - ProgressMonitorDialog dialog = new ProgressMonitorDialog(new Shell()); + ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); try { dialog.run(true, false, new LockAcquiringOperation()); // should not succeed @@ -63,5 +71,6 @@ public void testBug() throws CoreException { // lock. } }, workspace.getRoot(), IResource.NONE, null); + shell.close(); } } \ No newline at end of file diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug269121.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug269121.java index 85017f2b8a4..dfe0b5e2ebe 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug269121.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug269121.java @@ -29,7 +29,10 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.progress.UIJob; +import org.eclipse.ui.tests.SwtLeakTestWatcher; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; import junit.framework.AssertionFailedError; @@ -56,6 +59,9 @@ */ public class TestBug269121 { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + @Test public void testBug() throws InterruptedException, InvocationTargetException { @@ -73,8 +79,9 @@ protected void execute(IProgressMonitor monitor) { status.set(0, TestBarrier2.STATUS_DONE); } }; + Shell shell = new Shell(); final ProgressMonitorDialog dialog = new ProgressMonitorDialog( - new Shell()); + shell); Job statusJob = new Job("Checking for deadlock") { @Override protected IStatus run(IProgressMonitor monitor) { @@ -104,5 +111,6 @@ protected IStatus run(IProgressMonitor monitor) { } job.join(); assertTrue("Timeout occurred - possible Deadlock. See logging!", statusJob.getResult().isOK()); + shell.close(); } } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug98621.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug98621.java index 17965b8e366..19d75ec4078 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug98621.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/concurrency/TestBug98621.java @@ -28,7 +28,10 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.tests.SwtLeakTestWatcher; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; /** * Tests the following sequence of events: @@ -47,6 +50,10 @@ * @since 3.2 */ public class TestBug98621 { + + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + class TransferTestOperation extends WorkspaceModifyOperation { @Override public void execute(final IProgressMonitor pm) { @@ -80,8 +87,9 @@ public void threadChange(Thread thread) { */ @Test public void testBug() throws CoreException { + Shell shell = new Shell(); workspace.run((IWorkspaceRunnable) monitor -> { - ProgressMonitorDialog dialog = new ProgressMonitorDialog(new Shell()); + ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); try { dialog.run(true, false, new TransferTestOperation()); } catch (InvocationTargetException e1) { @@ -91,5 +99,6 @@ public void testBug() throws CoreException { // ignore } }, workspace.getRoot(), IResource.NONE, null); + shell.close(); } } \ No newline at end of file diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/DeprecatedUIPreferencesAuto.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/DeprecatedUIPreferencesAuto.java index ee1b127f8af..e8814c914ad 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/DeprecatedUIPreferencesAuto.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/DeprecatedUIPreferencesAuto.java @@ -13,6 +13,8 @@ *******************************************************************************/ package org.eclipse.ui.tests.dialogs; +import static org.junit.Assume.assumeNotNull; + import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.IPreferenceNode; import org.eclipse.jface.preference.PreferenceDialog; @@ -21,11 +23,17 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.IWorkbenchHelpContextIds; import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.eclipse.ui.tests.harness.util.DialogCheck; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; public class DeprecatedUIPreferencesAuto { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + protected Shell getShell() { return DialogCheck.getShell(); } @@ -122,23 +130,22 @@ public void testProjectReferencesProp() { @Test public void testFieldEditorEnablePref() { - PreferenceDialogWrapper dialog = null; PreferenceManager manager = WorkbenchPlugin.getDefault().getPreferenceManager(); - if (manager != null) { - dialog = new PreferenceDialogWrapper(getShell(), manager); - dialog.create(); - - for (IPreferenceNode node : manager.getElements(PreferenceManager.PRE_ORDER)) { - if (node.getId().equals("org.eclipse.ui.tests.dialogs.EnableTestPreferencePage")) { - dialog.showPage(node); - EnableTestPreferencePage page = (EnableTestPreferencePage) dialog.getPage(node); - page.flipState(); - page.flipState(); - break; - } + assumeNotNull(manager); + PreferenceDialogWrapper dialog = new PreferenceDialogWrapper( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), manager); + dialog.create(); + + for (IPreferenceNode node : manager.getElements(PreferenceManager.PRE_ORDER)) { + if (node.getId().equals("org.eclipse.ui.tests.dialogs.EnableTestPreferencePage")) { + dialog.showPage(node); + EnableTestPreferencePage page = (EnableTestPreferencePage) dialog.getPage(node); + page.flipState(); + page.flipState(); + break; } } - + dialog.close(); } } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIPreferencesAuto.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIPreferencesAuto.java index 90bebbd8074..43933de7d51 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIPreferencesAuto.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIPreferencesAuto.java @@ -13,6 +13,8 @@ *******************************************************************************/ package org.eclipse.ui.tests.dialogs; +import static org.junit.Assume.assumeNotNull; + import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.IPreferenceNode; import org.eclipse.jface.preference.PreferenceDialog; @@ -21,11 +23,16 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.IWorkbenchHelpContextIds; import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.eclipse.ui.tests.harness.util.DialogCheck; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; public class UIPreferencesAuto { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); protected Shell getShell() { return DialogCheck.getShell(); } @@ -124,25 +131,23 @@ public void testProjectReferencesProp() { */ @Test public void testFieldEditorEnablePref() { - - PreferenceDialogWrapper dialog = null; PreferenceManager manager = WorkbenchPlugin.getDefault() .getPreferenceManager(); - if (manager != null) { - dialog = new PreferenceDialogWrapper(getShell(), manager); - dialog.create(); - - for (IPreferenceNode node : manager.getElements(PreferenceManager.PRE_ORDER)) { - if (node.getId().equals("org.eclipse.ui.tests.dialogs.EnableTestPreferencePage")) { - dialog.showPage(node); - EnableTestPreferencePage page = (EnableTestPreferencePage) dialog.getPage(node); - page.flipState(); - page.flipState(); - break; - } + assumeNotNull(manager); + PreferenceDialogWrapper dialog = new PreferenceDialogWrapper( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), manager); + dialog.create(); + + for (IPreferenceNode node : manager.getElements(PreferenceManager.PRE_ORDER)) { + if (node.getId().equals("org.eclipse.ui.tests.dialogs.EnableTestPreferencePage")) { + dialog.showPage(node); + EnableTestPreferencePage page = (EnableTestPreferencePage) dialog.getPage(node); + page.flipState(); + page.flipState(); + break; } } - + dialog.close(); } } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIWizardsAuto.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIWizardsAuto.java index b9cbd0fc6d4..8c2dcf4b130 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIWizardsAuto.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/UIWizardsAuto.java @@ -39,6 +39,7 @@ import org.eclipse.ui.internal.dialogs.NewWizard; import org.eclipse.ui.internal.ide.IIDEHelpContextIds; import org.eclipse.ui.internal.wizards.newresource.ResourceMessages; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.eclipse.ui.tests.harness.util.DialogCheck; import org.eclipse.ui.tests.harness.util.FileUtil; import org.eclipse.ui.wizards.newresource.BasicNewFileResourceWizard; @@ -46,9 +47,14 @@ import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; import org.junit.After; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; public class UIWizardsAuto { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); + private static final int SIZING_WIZARD_WIDTH = 470; private static final int SIZING_WIZARD_HEIGHT = 550; @@ -332,7 +338,8 @@ private void checkWizardWindowTitle(String windowTitle) { initNewWizard(newWizard); - WizardDialog dialog = new WizardDialog(getShell(), newWizard); + WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + newWizard); dialog.create(); if(windowTitle == null) { diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/SupportTrayTest.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/SupportTrayTest.java index f9aae67eaa2..813f2ebe636 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/SupportTrayTest.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/SupportTrayTest.java @@ -37,11 +37,16 @@ import org.eclipse.ui.internal.statushandlers.StackTraceSupportArea; import org.eclipse.ui.internal.statushandlers.SupportTray; import org.eclipse.ui.statushandlers.StatusAdapter; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; public class SupportTrayTest { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); @After public void tearDown() throws Exception { @@ -100,9 +105,10 @@ public Control createSupportArea(Composite parent, IStatus status) { assertNotNull(st.providesSupport(sa)); + Shell shell = new Shell(); TrayDialog td = null; try { - td = new TrayDialog(new Shell()) { + td = new TrayDialog(shell) { }; td.setBlockOnOpen(false); td.open(); @@ -111,6 +117,7 @@ public Control createSupportArea(Composite parent, IStatus status) { if (td != null) { td.close(); } + shell.close(); } assertEquals(Status.OK_STATUS, _status[0]); @@ -138,8 +145,9 @@ public void testJFacePolicyOverDefaultPreference() { @Test public void testSelfClosure(){ final TrayDialog td[] = new TrayDialog[] { null }; + Shell shell = new Shell(); try { - td[0] = new TrayDialog(new Shell()) { + td[0] = new TrayDialog(shell) { }; Map dialogState = new HashMap<>(); dialogState.put(IStatusDialogConstants.CURRENT_STATUS_ADAPTER, new StatusAdapter(Status.OK_STATUS)); @@ -151,6 +159,7 @@ public void testSelfClosure(){ if (td != null) { td[0].close(); } + shell.close(); } } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/WizardsStatusHandlingTestCase.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/WizardsStatusHandlingTestCase.java index 197718edc90..b47e031a358 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/WizardsStatusHandlingTestCase.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/WizardsStatusHandlingTestCase.java @@ -35,10 +35,12 @@ import org.eclipse.ui.internal.dialogs.ExportWizard; import org.eclipse.ui.statushandlers.StatusAdapter; import org.eclipse.ui.statushandlers.StatusManager; -import org.eclipse.ui.tests.harness.util.DialogCheck; +import org.eclipse.ui.tests.SwtLeakTestWatcher; import org.eclipse.ui.tests.harness.util.UITestCase; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestWatcher; /** * Tests whether the errors in wizards are handled properly @@ -46,6 +48,8 @@ * @since 3.3 */ public class WizardsStatusHandlingTestCase { + @Rule + public TestWatcher swtLeakTestWatcher = new SwtLeakTestWatcher(); private static int SEVERITY = IStatus.ERROR; @@ -75,7 +79,7 @@ public void tearDown() throws Exception { } private Shell getShell() { - return DialogCheck.getShell(); + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); } private IWorkbench getWorkbench() {