blob: 16553442aa4c7a0b08671d7a9bd59d92153567ba [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2019 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
* Jeanderson Candido <http://jeandersonbc.github.io> - Bug 433603
*******************************************************************************/
package org.eclipse.ui.tests.services;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.expressions.ExpressionInfo;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.expressions.TestExpression;
import org.eclipse.core.expressions.WithExpression;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.internal.handlers.HandlerPersistence;
import org.eclipse.ui.services.IEvaluationReference;
import org.eclipse.ui.services.IEvaluationService;
import org.eclipse.ui.services.ISourceProviderService;
import org.eclipse.ui.tests.SelectionProviderView;
import org.eclipse.ui.tests.commands.ActiveContextExpression;
import org.eclipse.ui.tests.harness.util.UITestCase;
import org.junit.Assume;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.MethodSorters;
/**
* @since 3.3
*
*/
@RunWith(JUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class EvaluationServiceTest extends UITestCase {
/**
*
*/
private static final String CHECK_HANDLER_ID = "org.eclipse.ui.tests.services.checkHandler";
private static final String CONTEXT_ID1 = "org.eclipse.ui.command.contexts.evaluationService1";
public EvaluationServiceTest() {
super(EvaluationServiceTest.class.getName());
}
private static class MyEval implements IPropertyChangeListener {
public volatile int count = 0;
public volatile boolean currentValue;
@Override
public void propertyChange(PropertyChangeEvent event) {
count++;
if (event.getProperty() == IEvaluationService.RESULT
&& event.getNewValue() instanceof Boolean) {
currentValue = ((Boolean) event.getNewValue()).booleanValue();
}
}
}
@Test
public void testBug334524() throws Exception {
IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
IPerspectiveDescriptor resourecePerspective = registry.findPerspectiveWithId("org.eclipse.ui.resourcePerspective");
IPerspectiveDescriptor javaPerspective = registry.findPerspectiveWithId("org.eclipse.jdt.ui.JavaPerspective");
String viewId = "org.eclipse.ui.tests.SelectionProviderView";
IWorkbenchWindow window = openTestWindow();
IWorkbenchPage activePage = window.getActivePage();
// show view in resource perspective
activePage.setPerspective(resourecePerspective);
SelectionProviderView view = (SelectionProviderView) activePage.showView(viewId);
processEvents();
// show view in java perspective
activePage.setPerspective(javaPerspective);
activePage.showView(viewId);
processEvents();
// now set the selection
IStructuredSelection selection = new StructuredSelection(new String("testing selection"));
view.setSelection(selection);
processEvents();
// switch perspective & check selection
activePage.setPerspective(resourecePerspective);
processEvents();
IEvaluationService service = window.getService(IEvaluationService.class);
Object currentSelection = service.getCurrentState().getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME);
assertEquals(selection, currentSelection);
}
@Test
public void testBasicService() throws Exception {
IWorkbenchWindow window = openTestWindow();
waitForJobs(500, 5000);
boolean activeShell = forceActive(window.getShell());
Assume.assumeTrue(activeShell);
IEvaluationService service = window
.getService(IEvaluationService.class);
assertNotNull(service);
MyEval listener = new MyEval();
IContextActivation context1 = null;
IEvaluationReference evalRef = null;
IContextService contextService = null;
try {
contextService = window.getService(IContextService.class);
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
evalRef = service.addEvaluationListener(
new ActiveContextExpression(CONTEXT_ID1,
new String[] { ISources.ACTIVE_CONTEXT_NAME }),
listener, IEvaluationService.RESULT);
assertEquals(1, listener.count);
assertFalse(listener.currentValue);
context1 = contextService.activateContext(CONTEXT_ID1);
processEvents();
waitForJobs(500, 3000);
assertTrue(contextService.getActiveContextIds().contains(CONTEXT_ID1));
assertEquals(2, listener.count);
assertTrue(listener.currentValue);
contextService.deactivateContext(context1);
context1 = null;
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
assertEquals(3, listener.count);
assertFalse(listener.currentValue);
service.removeEvaluationListener(evalRef);
evalRef = null;
assertEquals(4, listener.count);
context1 = contextService.activateContext(CONTEXT_ID1);
processEvents();
waitForJobs(500, 3000);
assertTrue(contextService.getActiveContextIds().contains(CONTEXT_ID1));
assertEquals(4, listener.count);
assertFalse(listener.currentValue);
contextService.deactivateContext(context1);
context1 = null;
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
assertEquals(4, listener.count);
assertFalse(listener.currentValue);
} finally {
if (context1 != null) {
contextService.deactivateContext(context1);
}
if (evalRef != null) {
service.removeEvaluationListener(evalRef);
}
}
}
@Test
public void testTwoEvaluations() throws Exception {
IWorkbenchWindow window = openTestWindow();
boolean activeShell = forceActive(window.getShell());
waitForJobs(500, 5000);
final AtomicBoolean shellIsActive = new AtomicBoolean(activeShell);
Assume.assumeTrue(shellIsActive.get());
IEvaluationService service = window
.getService(IEvaluationService.class);
assertNotNull(service);
MyEval listener1 = new MyEval();
MyEval listener2 = new MyEval();
IContextActivation context1 = null;
IEvaluationReference evalRef1 = null;
IEvaluationReference evalRef2 = null;
IContextService contextService = null;
try {
contextService = window.getService(IContextService.class);
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
evalRef1 = service.addEvaluationListener(
new ActiveContextExpression(CONTEXT_ID1,
new String[] { ISources.ACTIVE_CONTEXT_NAME }),
listener1, IEvaluationService.RESULT);
assertEquals(1, listener1.count);
assertFalse(listener1.currentValue);
evalRef2 = service.addEvaluationListener(
new ActiveContextExpression(CONTEXT_ID1,
new String[] { ISources.ACTIVE_CONTEXT_NAME }),
listener2, IEvaluationService.RESULT);
assertEquals(1, listener2.count);
assertFalse(listener2.currentValue);
evalRef2.setResult(true);
context1 = contextService.activateContext(CONTEXT_ID1);
processEvents();
waitForJobs(500, 3000);
assertTrue(contextService.getActiveContextIds().contains(CONTEXT_ID1));
int count = 0;
while (count < 5 && listener1.count != 2) {
count++;
waitForJobs(100 * count, 1000);
}
assertEquals(2, listener1.count);
assertTrue(listener1.currentValue);
// we already set this guy to true, he should skip
assertEquals(1, listener2.count);
assertFalse(listener2.currentValue);
evalRef1.setResult(false);
contextService.deactivateContext(context1);
processEvents();
waitForJobs(500, 3000);
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
context1 = null;
assertEquals(2, listener2.count);
assertFalse(listener2.currentValue);
// we already set this guy to false, so he should be the old
// values
assertEquals(2, listener1.count);
assertTrue(listener1.currentValue);
} finally {
if (context1 != null) {
contextService.deactivateContext(context1);
}
if (evalRef1 != null) {
service.removeEvaluationListener(evalRef1);
}
if (evalRef2 != null) {
service.removeEvaluationListener(evalRef2);
}
}
}
@Test
@Ignore // TODO fix testRestriction
public void testRestriction() {
IWorkbenchWindow window = openTestWindow();
IEvaluationService evaluationService = window
.getService(IEvaluationService.class);
assertNotNull(evaluationService);
IContextService contextService = window
.getService(IContextService.class);
assertNotNull(contextService);
Expression expression = new ActiveContextExpression(CONTEXT_ID1,
new String[] { ISources.ACTIVE_CONTEXT_NAME });
final boolean[] propertyChanged = new boolean[1];
final boolean[] propertyShouldChange = new boolean[1];
IPropertyChangeListener propertyChangeListener = event -> {
if (event.getProperty().equals("foo")) {
propertyChanged[0] = true;
}
};
IEvaluationReference ref = evaluationService.addEvaluationListener(
expression, propertyChangeListener, "foo");
((WorkbenchWindow)window).getMenuRestrictions().add(ref);
IPropertyChangeListener propertyShouldChangeListener = event -> {
if (event.getProperty().equals("foo")) {
propertyShouldChange[0] = true;
}
};
evaluationService.addEvaluationListener(expression,
propertyShouldChangeListener, "foo");
propertyChanged[0] = false;
propertyShouldChange[0] = false;
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
IContextActivation activation = contextService
.activateContext(CONTEXT_ID1);
assertTrue(propertyChanged[0]);
assertTrue(propertyShouldChange[0]);
propertyChanged[0] = false;
propertyShouldChange[0] = false;
contextService.deactivateContext(activation);
assertTrue(propertyChanged[0]);
assertTrue(propertyShouldChange[0]);
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
activation = contextService.activateContext(CONTEXT_ID1);
propertyChanged[0] = false;
propertyShouldChange[0] = false;
assertTrue(contextService.getActiveContextIds().contains(CONTEXT_ID1));
// open second window
IWorkbenchWindow window2 = openTestWindow();
assertFalse(propertyChanged[0]);
assertTrue(propertyShouldChange[0]);
assertFalse(contextService.getActiveContextIds().contains(CONTEXT_ID1));
propertyChanged[0] = false;
propertyShouldChange[0] = false;
window2.close();
processEvents();
assertTrue(contextService.getActiveContextIds().contains(CONTEXT_ID1));
assertFalse(propertyChanged[0]);
assertTrue(propertyShouldChange[0]);
}
@Test
@Ignore // TODO fix testScopedService
public void testScopedService() throws Exception {
IWorkbenchWindow window = openTestWindow();
IEvaluationService service = window
.getService(IEvaluationService.class);
assertNotNull(service);
//assertTrue(service instanceof SlaveEvaluationService);
MyEval listener = new MyEval();
IContextActivation context1 = null;
IContextService contextService = null;
try {
service.addEvaluationListener(
new ActiveContextExpression(CONTEXT_ID1,
new String[] { ISources.ACTIVE_CONTEXT_NAME }),
listener, IEvaluationService.RESULT);
assertEquals(1, listener.count);
assertFalse(listener.currentValue);
contextService = window.getWorkbench()
.getService(IContextService.class);
context1 = contextService.activateContext(CONTEXT_ID1);
assertEquals(2, listener.count);
assertTrue(listener.currentValue);
window.close();
processEvents();
assertEquals(3, listener.count);
assertTrue(listener.currentValue);
contextService.deactivateContext(context1);
context1 = null;
assertEquals(3, listener.count);
assertTrue(listener.currentValue);
} finally {
if (context1 != null) {
contextService.deactivateContext(context1);
}
}
}
private static class UserExpression extends Expression {
public String lookFor;
public UserExpression(String lookFor) {
this.lookFor = lookFor;
}
@Override
public void collectExpressionInfo(ExpressionInfo info) {
info.addVariableNameAccess("username");
}
@Override
public EvaluationResult evaluate(IEvaluationContext context) {
String variable = (String) context.getVariable("username");
return lookFor.equals(variable) ? EvaluationResult.TRUE
: EvaluationResult.FALSE;
}
}
@Test
public void testSourceProvider() throws Exception {
IWorkbenchWindow window = openTestWindow();
IEvaluationService service = window
.getService(IEvaluationService.class);
assertNotNull(service);
MyEval listener = new MyEval();
UserExpression expression = new UserExpression("Paul");
IEvaluationReference ref = service.addEvaluationListener(expression,
listener, IEvaluationService.RESULT);
assertEquals(ISources.ACTIVE_CONTEXT << 1, ref.getSourcePriority());
assertFalse(listener.currentValue);
assertEquals(1, listener.count);
ISourceProviderService sps = window
.getService(ISourceProviderService.class);
ActiveUserSourceProvider userProvider = (ActiveUserSourceProvider) sps
.getSourceProvider("username");
userProvider.setUsername("John");
assertFalse(listener.currentValue);
assertEquals(1, listener.count);
userProvider.setUsername("Paul");
assertTrue(listener.currentValue);
assertEquals(2, listener.count);
userProvider.setUsername("guest");
assertFalse(listener.currentValue);
assertEquals(3, listener.count);
}
@Test
@SuppressWarnings("unchecked")
public void testSourceProviderPriority() throws Exception {
IHandlerService hs = getWorkbench().getService(IHandlerService.class);
Collection<IHandlerActivation> activations = null;
// fill in a set of activations
String hsClassName = hs.getClass().getName();
switch (hsClassName) {
case "org.eclipse.ui.internal.handlers.HandlerService":
{
Field hpField = hs.getClass().getDeclaredField("handlerPersistence");
hpField.setAccessible(true);
HandlerPersistence hp = (HandlerPersistence) hpField.get(hs);
Field activationsField = hp.getClass().getDeclaredField("handlerActivations");
activationsField.setAccessible(true);
activations = (Collection<IHandlerActivation>) activationsField.get(hp);
assertNotNull(activations);
break;
}
case "org.eclipse.ui.internal.handlers.LegacyHandlerService":
{
Field hsField = hs.getClass().getDeclaredField("LEGACY_H_ID");
String LEGACY_H_ID = (String) hsField.get(null);
Field hpField = hs.getClass().getDeclaredField("eclipseContext");
hpField.setAccessible(true);
Object eclipseContext = hpField.get(hs);
assertNotNull(eclipseContext);
Method getMethod = eclipseContext.getClass().getDeclaredMethod("get", String.class);
activations = (Collection<IHandlerActivation>) getMethod.invoke(eclipseContext,
LEGACY_H_ID + CHECK_HANDLER_ID);
assertNotNull(activations);
break;
}
default:
fail("Incorrect handler service: " + hsClassName);
break;
}
IHandlerActivation activation = null;
Iterator<IHandlerActivation> i = activations.iterator();
while (i.hasNext()) {
IHandlerActivation ha = i.next();
if (CHECK_HANDLER_ID.equals(ha.getCommandId())) {
activation = ha;
}
}
assertNotNull("Could not find activation for " + CHECK_HANDLER_ID, activation);
assertEquals(ISources.ACTIVE_CONTEXT<<1, activation.getSourcePriority());
}
@Test
public void testPropertyChange() throws Exception {
IWorkbenchWindow window = openTestWindow();
IEvaluationService service = window
.getService(IEvaluationService.class);
assertNotNull(service);
MyEval listener = new MyEval();
IExtensionRegistry registry = Platform.getExtensionRegistry();
IConfigurationElement element = null;
IConfigurationElement[] elements = registry
.getConfigurationElementsFor("org.eclipse.core.expressions.definitions");
for (int i = 0; i < elements.length && element == null; i++) {
if (elements[i].getAttribute("id").equals(
"org.eclipse.ui.tests.defWithPropertyTester")) {
element = elements[i];
}
}
assertNotNull(element);
Expression expr = ExpressionConverter.getDefault().perform(element.getChildren()[0]);
service.addEvaluationListener(expr,
listener, IEvaluationService.RESULT);
assertFalse(listener.currentValue);
assertEquals(1, listener.count);
StaticVarPropertyTester.result = true;
assertFalse(listener.currentValue);
assertEquals(1, listener.count);
service.requestEvaluation("org.eclipse.ui.tests.class.method");
assertTrue(listener.currentValue);
assertEquals(2, listener.count);
service.requestEvaluation("org.eclipse.ui.tests.class.method");
assertTrue(listener.currentValue);
assertEquals(2, listener.count);
}
@Test
public void testPlatformProperty() throws Exception {
IEvaluationService evaluationService = PlatformUI
.getWorkbench().getService(IEvaluationService.class);
TestExpression test = new TestExpression("org.eclipse.core.runtime",
"bundleState",
new Object[] { "org.eclipse.core.expressions" }, "ACTIVE", false);
WithExpression exp = new WithExpression("org.eclipse.core.runtime.Platform");
exp.add(test);
EvaluationResult result= exp.evaluate(evaluationService.getCurrentState());
assertEquals(EvaluationResult.TRUE, result);
}
@Test
@Ignore
public void testSystemProperty() throws Exception {
// this is not added, as the ability to test system properties with
// no '.' seems unhelpful
System.setProperty("isHere", "true");
IEvaluationService evaluationService = PlatformUI
.getWorkbench().getService(IEvaluationService.class);
TestExpression test = new TestExpression("org.eclipse.core.runtime",
"isHere",
new Object[] { "true" }, null, false);
WithExpression exp = new WithExpression(
"java.lang.System" );
exp.add(test);
EvaluationResult result = exp.evaluate(evaluationService
.getCurrentState());
assertEquals(EvaluationResult.TRUE, result);
}
static class ActivePartIdExpression extends Expression {
private String partId;
public ActivePartIdExpression(String id) {
partId = id;
}
@Override
public void collectExpressionInfo(ExpressionInfo info) {
info.addVariableNameAccess(ISources.ACTIVE_PART_ID_NAME);
info.addVariableNameAccess(ISources.ACTIVE_CURRENT_SELECTION_NAME);
}
@Override
public EvaluationResult evaluate(IEvaluationContext context){
Object v = context.getVariable(ISources.ACTIVE_PART_ID_NAME);
return EvaluationResult.valueOf(partId.equals(v));
}
}
static class PartSelection {
public ISelection selection;
public IWorkbenchPart part;
public PartSelection(ISelection sel, IWorkbenchPart p) {
selection = sel;
part = p;
}
}
@Test
public void testWorkbenchProvider() throws Exception {
IWorkbenchWindow window = openTestWindow();
final IEvaluationService service = window
.getWorkbench().getService(IEvaluationService.class);
assertNotNull(service);
// some setup
IWorkbenchPage page = window.getActivePage();
SelectionProviderView view1 = (SelectionProviderView) page
.showView(org.eclipse.ui.tests.SelectionProviderView.ID);
view1.setSelection(StructuredSelection.EMPTY);
SelectionProviderView view2 = (SelectionProviderView) page
.showView(org.eclipse.ui.tests.SelectionProviderView.ID_2);
TextSelection mySelection = new TextSelection(0, 5);
view2.setSelection(mySelection);
processEvents();
final ArrayList<PartSelection> selection = new ArrayList<>();
IPropertyChangeListener listener = event -> {
IEvaluationContext state = service.getCurrentState();
try {
ISelection sel = null;
IWorkbenchPart part = null;
Object o = state
.getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME);
if (o instanceof ISelection) {
sel = (ISelection) o;
}
o = state.getVariable(ISources.ACTIVE_PART_NAME);
if (o instanceof IWorkbenchPart) {
part = (IWorkbenchPart) o;
}
selection.add(new PartSelection(sel, part));
} catch (Exception e) {
e.printStackTrace();
}
};
IEvaluationReference ref = service.addEvaluationListener(
new ActivePartIdExpression(
org.eclipse.ui.tests.SelectionProviderView.ID),
listener, "PROP");
int callIdx = 0;
try {
// initially ID_2 is showed
assertSelection(selection, callIdx, TextSelection.class, SelectionProviderView.ID_2);
page.activate(view1);
processEvents();
callIdx++;
assertSelection(selection, callIdx, StructuredSelection.class, SelectionProviderView.ID);
page.activate(view2);
processEvents();
callIdx++;
assertSelection(selection, callIdx, TextSelection.class, SelectionProviderView.ID_2);
assertEquals(window.getActivePage().getActivePart().getSite().getId(),
service.getCurrentState().getVariable(ISources.ACTIVE_PART_ID_NAME));
IWorkbenchWindow window2 = openTestWindow();
IWorkbenchPage page2 = window2.getActivePage();
processEvents();
// no change
assertEquals(callIdx + 1, selection.size());
SelectionProviderView view3 = (SelectionProviderView) page2
.showView(org.eclipse.ui.tests.SelectionProviderView.ID);
processEvents();
// id1 activated with default selection StructuredSelection.EMPTY
callIdx++;
assertSelection(selection, callIdx, StructuredSelection.class, SelectionProviderView.ID);
assertEquals(window2.getActivePage().getActivePart().getSite().getId(),
service.getCurrentState().getVariable(ISources.ACTIVE_PART_ID_NAME));
view3.setSelection(new TreeSelection(new TreePath(new Object[] {"nothing"})));
processEvents();
// selection changes, but view id remains the same - so no callIdx increments
assertEquals(callIdx + 1, selection.size());
window.getShell().forceActive();
processEvents();
// the shell activate should have forced another change
callIdx++;
// assertEquals(window.getActivePage().getActivePart().getSite().getId(),
// service.getCurrentState().getVariable(ISources.ACTIVE_PART_ID_NAME));
// assertSelection(selection, callIdx, TextSelection.class, SelectionProviderView.ID_2);
} finally {
service.removeEvaluationListener(ref);
}
}
private void assertSelection(final ArrayList<PartSelection> selection, int callIdx, Class<?> clazz, String viewId) {
assertEquals(callIdx + 1, selection.size());
assertEquals(clazz, getSelection(selection, callIdx)
.getClass());
assertEquals(viewId, getPart(selection, callIdx).getSite().getId());
}
private ISelection getSelection(final ArrayList<PartSelection> selection, int idx) {
return selection.get(idx).selection;
}
private IWorkbenchPart getPart(final ArrayList<PartSelection> selection, int idx) {
return selection.get(idx).part;
}
}