blob: caee242d9d3001bbbd4c1ee2ebcfede1425660ab [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 InterSystems 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:
* Vasili Gulevich - Bug 501404
*******************************************************************************/
package org.eclipse.ui.internal.ide.application;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.Closeable;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class IDEWorkbenchAdvisorTest {
private static final String PLUGIN_ID = "org.eclipse.ui.ide.application.tests";
private Display display = null;
private ISchedulingRule rule;
private static final class SaveHook implements ISaveParticipant, Closeable {
public ISaveContext saving = null;
public ISaveContext rollback = null;
public ISaveContext prepareToSave = null;
public ISaveContext doneSaving = null;
public final IWorkspace workspace = ResourcesPlugin.getWorkspace();
public SaveHook() throws CoreException {
workspace.addSaveParticipant(PLUGIN_ID, this);
}
@Override
public void saving(ISaveContext context) {
saving = context;
}
@Override
public void rollback(ISaveContext context) {
rollback = context;
}
@Override
public void prepareToSave(ISaveContext context) {
prepareToSave = context;
}
@Override
public void doneSaving(ISaveContext context) {
doneSaving = context;
}
@Override
public void close() {
workspace.removeSaveParticipant(PLUGIN_ID);
}
}
@Before
public void setUp() {
assertNull(display);
display = PlatformUI.createDisplay();
assertNotNull(display);
rule = ResourcesPlugin.getWorkspace().getRoot();
}
@After
public void tearDown() throws Exception {
try {
Job.getJobManager().endRule(rule);
} catch (IllegalArgumentException e) {
// ignore, if the rule is not held by this thread
}
dispatchDisplay();
display.dispose();
assertTrue(display.isDisposed());
display = null;
}
/**
* Workbench shutdown should not deadlock when invoked from workspace
* operation
*
* Regression test for bug 501404 Timeout annotation parameter can't be
* used, as it makes test to be executed in non-UI thread.
*
*/
@Test
public void testShutdownWithLockedWorkspace() throws CoreException {
try (SaveHook saveHook = new SaveHook()) {
IDEWorkbenchAdvisor advisor = new IDEWorkbenchAdvisor() {
@Override
public void postStartup() {
super.postStartup();
display.asyncExec(() -> {
Job.getJobManager().beginRule(rule, null);
try {
PlatformUI.getWorkbench().close();
} finally {
Job.getJobManager().endRule(rule);
}
});
}
};
int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);
Assert.assertEquals(PlatformUI.RETURN_OK, returnCode);
dispatchDisplay();
Assert.assertNotNull(saveHook.prepareToSave);
Assert.assertNotNull(saveHook.saving);
Assert.assertNotNull(saveHook.prepareToSave);
Assert.assertNotNull(saveHook.doneSaving);
Assert.assertNull(saveHook.rollback);
}
}
/**
* Workbench shutdown should not deadlock when invoked from workspace
* operation
*
* Regression test for bug 501404 Timeout annotation parameter can't be
* used, as it makes test to be executed in non-UI thread.
*
*/
@Test
public void testShutdownWithForeverLockedWorkspace() throws CoreException {
AtomicInteger logs = new AtomicInteger();
final int expectedLogs = 4;
ILogListener listener = (status, plugin) -> {
if (status.getMessage().equals(IDEWorkbenchMessages.ProblemsSavingWorkspace)) {
logs.addAndGet(1);
}
};
try (SaveHook saveHook = new SaveHook()) {
IDEWorkbenchPlugin.getDefault().getLog().addLogListener(listener);
IDEWorkbenchAdvisor advisor = new IDEWorkbenchAdvisor(100, null) {
@Override
public void postStartup() {
super.postStartup();
display.asyncExec(() -> {
Job.getJobManager().beginRule(rule, null);
PlatformUI.getWorkbench().close();
// no end rule
});
}
@Override
public void postShutdown() {
super.postShutdown();
long start = System.currentTimeMillis();
long stop = start + 5_000;
while (logs.get() < expectedLogs && System.currentTimeMillis() < stop) {
try {
dispatchDisplay();
Thread.sleep(50);
} catch (Exception e) {
// ignore
}
}
}
};
int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);
Assert.assertEquals(PlatformUI.RETURN_OK, returnCode);
dispatchDisplay();
Assert.assertNull(saveHook.prepareToSave);
Assert.assertNull(saveHook.saving);
Assert.assertNull(saveHook.prepareToSave);
Assert.assertNull(saveHook.doneSaving);
Assert.assertNull(saveHook.rollback);
String message = "IDEWorkbenchAdvisor did not properly reported failed disconnect";
Assert.assertEquals(message, expectedLogs, logs.get());
} finally {
IDEWorkbenchPlugin.getDefault().getLog().removeLogListener(listener);
}
}
/**
* Workbench shutdown should disconnect workspace if it is not locked
*
* Regression test for bug 501404 Timeout annotation parameter can't be
* used, as it makes test to be executed in non-UI thread.
*/
@Test
public void testShutdownWithUnlockedWorkspace() throws CoreException {
try (SaveHook saveHook = new SaveHook()) {
IDEWorkbenchAdvisor advisor = new IDEWorkbenchAdvisor() {
@Override
public void postStartup() {
super.postStartup();
display.asyncExec(() -> {
PlatformUI.getWorkbench().close();
});
}
};
int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);
Assert.assertEquals(PlatformUI.RETURN_OK, returnCode);
dispatchDisplay();
Assert.assertNotNull(saveHook.prepareToSave);
Assert.assertNotNull(saveHook.saving);
Assert.assertNotNull(saveHook.prepareToSave);
Assert.assertNotNull(saveHook.doneSaving);
Assert.assertNull(saveHook.rollback);
}
}
/**
* Process display events until there are none left
*/
private void dispatchDisplay() {
while (display.readAndDispatch()) {
;
}
}
}