blob: 6163253422cd678b43123bc15ab6da095cd2aceb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 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.debug.tests.expressions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IExpressionListener;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.IExpressionsListener;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IWatchExpression;
import org.eclipse.debug.internal.core.ExpressionManager;
import org.eclipse.debug.internal.core.IExpressionsListener2;
import org.eclipse.debug.tests.AbstractDebugTest;
import org.junit.After;
import org.junit.Test;
/**
* Tests expression manager and listener call backs
*/
public class ExpressionManagerTests extends AbstractDebugTest {
class SinlgeListener implements IExpressionListener {
List<IExpression> added = new ArrayList<>();
List<IExpression> removed = new ArrayList<>();
List<IExpression> changed = new ArrayList<>();
int addedCallbacks = 0;
int removedCallbacks = 0;
int changedCallbacks = 0;
@Override
public void expressionAdded(IExpression expression) {
added.add(expression);
addedCallbacks++;
}
@Override
public void expressionRemoved(IExpression expression) {
removed.add(expression);
removedCallbacks++;
}
@Override
public void expressionChanged(IExpression expression) {
changed.add(expression);
changedCallbacks++;
}
}
class MultiListener implements IExpressionsListener {
List<IExpression> added = new ArrayList<>();
List<IExpression> removed = new ArrayList<>();
List<IExpression> changed = new ArrayList<>();
int addedCallbacks = 0;
int removedCallbacks = 0;
int changedCallbacks = 0;
@Override
public void expressionsAdded(IExpression[] expressions) {
Collections.addAll(added, expressions);
addedCallbacks++;
}
@Override
public void expressionsRemoved(IExpression[] expressions) {
Collections.addAll(removed, expressions);
removedCallbacks++;
}
@Override
public void expressionsChanged(IExpression[] expressions) {
Collections.addAll(changed, expressions);
changedCallbacks++;
}
}
class InsertMoveListener extends MultiListener implements IExpressionsListener2 {
List<IExpression> moved = new ArrayList<>();
List<IExpression> inserted = new ArrayList<>();
int insertIndex = -1;
int movedCallbacks = 0;
int insertedCallbacks = 0;
@Override
public void expressionsMoved(IExpression[] expressions, int index) {
Collections.addAll(moved, expressions);
movedCallbacks++;
insertIndex = index;
}
@Override
public void expressionsInserted(IExpression[] expressions, int index) {
Collections.addAll(inserted, expressions);
insertedCallbacks++;
insertIndex = index;
}
}
/**
* Returns the expression manager.
*
* @return expression manager
*/
protected IExpressionManager getManager() {
return DebugPlugin.getDefault().getExpressionManager();
}
@Override
@After
public void tearDown() throws Exception {
// remove all expressions from the manager
getManager().removeExpressions(getManager().getExpressions());
super.tearDown();
}
/**
* Returns the index of the given expression in the given list or -1 if not present.
*
* @param expression candidate
* @param list list to search
* @return index or -1
*/
private int indexOf(IExpression expression, IExpression[] list) {
for (int i = 0; i < list.length; i++) {
if (expression.equals(list[i])) {
return i;
}
}
return -1;
}
/**
* Add expressions and ensure proper call backs are received.
*/
@Test
public void testAddExpressions() {
IExpressionManager manager = getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 3, expressions.length); //$NON-NLS-1$
assertEquals(single.addedCallbacks, 3);
assertEquals(3, single.added.size());
assertEquals(0, single.added.indexOf(exp1));
assertEquals(1, single.added.indexOf(exp2));
assertEquals(2, single.added.indexOf(exp3));
assertEquals(0, single.removedCallbacks);
assertEquals(0, single.changedCallbacks);
assertEquals(1, multi.addedCallbacks);
assertEquals(0, multi.removedCallbacks);
assertEquals(0, multi.changedCallbacks);
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp2, expressions));
assertEquals(2, indexOf(exp3, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
}
}
/**
* Remove expressions and ensure proper call backs are received.
*/
@Test
public void testRemoveExpressions() {
IExpressionManager manager = getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
manager.removeExpressions(new IExpression[]{exp1, exp3});
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 1, expressions.length); //$NON-NLS-1$
assertEquals(single.addedCallbacks, 3);
assertEquals(3, single.added.size());
assertEquals(0, single.added.indexOf(exp1));
assertEquals(1, single.added.indexOf(exp2));
assertEquals(2, single.added.indexOf(exp3));
assertEquals(2, single.removedCallbacks);
assertEquals(0, single.removed.indexOf(exp1));
assertEquals(1, single.removed.indexOf(exp3));
assertEquals(0, single.changedCallbacks);
assertEquals(1, multi.addedCallbacks);
assertEquals(1, multi.removedCallbacks);
assertEquals(0, multi.removed.indexOf(exp1));
assertEquals(1, multi.removed.indexOf(exp3));
assertEquals(0, multi.changedCallbacks);
assertEquals(-1, indexOf(exp1, expressions));
assertEquals(0, indexOf(exp2, expressions));
assertEquals(-1, indexOf(exp3, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
}
}
/**
* Change expressions and ensure proper call backs are received.
*/
@Test
public void testChangeExpressions() {
IExpressionManager manager = getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
IExpression[] expressions = manager.getExpressions();
exp1.setEnabled(false);
exp2.setExpressionText("exp2changed"); //$NON-NLS-1$
assertEquals("Wrong number of expressions", 3, expressions.length); //$NON-NLS-1$
assertEquals(single.addedCallbacks, 3);
assertEquals(3, single.added.size());
assertEquals(0, single.added.indexOf(exp1));
assertEquals(1, single.added.indexOf(exp2));
assertEquals(2, single.added.indexOf(exp3));
assertEquals(0, single.removedCallbacks);
assertEquals(2, single.changedCallbacks);
assertEquals(0, single.changed.indexOf(exp1));
assertEquals(1, single.changed.indexOf(exp2));
assertEquals(1, multi.addedCallbacks);
assertEquals(0, multi.removedCallbacks);
assertEquals(2, multi.changedCallbacks);
assertEquals(0, multi.changed.indexOf(exp1));
assertEquals(1, multi.changed.indexOf(exp2));
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp2, expressions));
assertEquals(2, indexOf(exp3, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
}
}
/**
* Insert expressions and ensure proper call backs are received.
*/
@Test
public void testInsertBeforeExpressions() {
ExpressionManager manager = (ExpressionManager) getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
InsertMoveListener insert = new InsertMoveListener();
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
IWatchExpression exp4 = manager.newWatchExpression("exp4"); //$NON-NLS-1$
IWatchExpression exp5 = manager.newWatchExpression("exp5"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 3, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp2, expressions));
assertEquals(2, indexOf(exp3, expressions));
// add listeners
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
manager.addExpressionListener(insert);
manager.insertExpressions(new IExpression[] {exp4, exp5}, exp2, true);
assertEquals(2, single.addedCallbacks);
assertEquals(2, single.added.size());
assertEquals(0, single.removedCallbacks);
assertEquals(0, single.changedCallbacks);
assertEquals(1, multi.addedCallbacks);
assertEquals(2, multi.added.size());
assertEquals(0, multi.removedCallbacks);
assertEquals(0, multi.changedCallbacks);
assertEquals(1, insert.insertedCallbacks);
assertEquals(1, insert.insertIndex);
assertEquals(0, insert.movedCallbacks);
assertEquals(2, insert.inserted.size());
assertEquals(0, insert.inserted.indexOf(exp4));
assertEquals(1, insert.inserted.indexOf(exp5));
expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 5, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp4, expressions));
assertEquals(2, indexOf(exp5, expressions));
assertEquals(3, indexOf(exp2, expressions));
assertEquals(4, indexOf(exp3, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
manager.removeExpressionListener(insert);
}
}
/**
* Insert expressions and ensure proper call backs are received.
*/
@Test
public void testInsertAfterExpressions() {
ExpressionManager manager = (ExpressionManager) getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
InsertMoveListener insert = new InsertMoveListener();
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
IWatchExpression exp4 = manager.newWatchExpression("exp4"); //$NON-NLS-1$
IWatchExpression exp5 = manager.newWatchExpression("exp5"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 3, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp2, expressions));
assertEquals(2, indexOf(exp3, expressions));
// add listeners
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
manager.addExpressionListener(insert);
manager.insertExpressions(new IExpression[] {exp4, exp5}, exp2, false);
assertEquals(2, single.addedCallbacks);
assertEquals(2, single.added.size());
assertEquals(0, single.removedCallbacks);
assertEquals(0, single.changedCallbacks);
assertEquals(1, multi.addedCallbacks);
assertEquals(2, multi.added.size());
assertEquals(0, multi.removedCallbacks);
assertEquals(0, multi.changedCallbacks);
assertEquals(1, insert.insertedCallbacks);
assertEquals(2, insert.insertIndex);
assertEquals(0, insert.movedCallbacks);
assertEquals(2, insert.inserted.size());
assertEquals(0, insert.inserted.indexOf(exp4));
assertEquals(1, insert.inserted.indexOf(exp5));
expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 5, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp1, expressions));
assertEquals(1, indexOf(exp2, expressions));
assertEquals(2, indexOf(exp4, expressions));
assertEquals(3, indexOf(exp5, expressions));
assertEquals(4, indexOf(exp3, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
manager.removeExpressionListener(insert);
}
}
/**
* Move expressions and ensure proper call backs are received.
*/
@Test
public void testMoveBeforeExpressions() {
ExpressionManager manager = (ExpressionManager) getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
InsertMoveListener insert = new InsertMoveListener();
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
IWatchExpression exp4 = manager.newWatchExpression("exp4"); //$NON-NLS-1$
IWatchExpression exp5 = manager.newWatchExpression("exp5"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
// add listeners
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
manager.addExpressionListener(insert);
manager.moveExpressions(new IExpression[]{exp1,exp2}, exp5, true);
assertEquals(0, single.addedCallbacks);
assertEquals(0, single.removedCallbacks);
assertEquals(0, single.changedCallbacks);
assertEquals(0, multi.addedCallbacks);
assertEquals(0, multi.removedCallbacks);
assertEquals(0, multi.changedCallbacks);
assertEquals(0, insert.insertedCallbacks);
assertEquals(1, insert.movedCallbacks);
assertEquals(2, insert.moved.size());
assertEquals(0, insert.moved.indexOf(exp1));
assertEquals(1, insert.moved.indexOf(exp2));
assertEquals(2, insert.insertIndex);
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 5, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp3, expressions));
assertEquals(1, indexOf(exp4, expressions));
assertEquals(2, indexOf(exp1, expressions));
assertEquals(3, indexOf(exp2, expressions));
assertEquals(4, indexOf(exp5, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
manager.removeExpressionListener(insert);
}
}
/**
* Move expressions and ensure proper call backs are received.
*/
@Test
public void testMoveAfterExpressions() {
ExpressionManager manager = (ExpressionManager) getManager();
SinlgeListener single = new SinlgeListener();
MultiListener multi = new MultiListener();
InsertMoveListener insert = new InsertMoveListener();
try {
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
IWatchExpression exp4 = manager.newWatchExpression("exp4"); //$NON-NLS-1$
IWatchExpression exp5 = manager.newWatchExpression("exp5"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
// add listeners
manager.addExpressionListener(single);
manager.addExpressionListener(multi);
manager.addExpressionListener(insert);
manager.moveExpressions(new IExpression[]{exp1,exp2}, exp3, false);
assertEquals(0, single.addedCallbacks);
assertEquals(0, single.removedCallbacks);
assertEquals(0, single.changedCallbacks);
assertEquals(0, multi.addedCallbacks);
assertEquals(0, multi.removedCallbacks);
assertEquals(0, multi.changedCallbacks);
assertEquals(0, insert.insertedCallbacks);
assertEquals(1, insert.movedCallbacks);
assertEquals(2, insert.moved.size());
assertEquals(0, insert.moved.indexOf(exp1));
assertEquals(1, insert.moved.indexOf(exp2));
assertEquals(1, insert.insertIndex);
IExpression[] expressions = manager.getExpressions();
assertEquals("Wrong number of expressions", 5, expressions.length); //$NON-NLS-1$
assertEquals(0, indexOf(exp3, expressions));
assertEquals(1, indexOf(exp1, expressions));
assertEquals(2, indexOf(exp2, expressions));
assertEquals(3, indexOf(exp4, expressions));
assertEquals(4, indexOf(exp5, expressions));
} finally {
manager.removeExpressionListener(single);
manager.removeExpressionListener(multi);
manager.removeExpressionListener(insert);
}
}
/**
* Test persist and restore of expressions
*/
@Test
public void testPersistExpressions() {
ExpressionManager manager = (ExpressionManager) getManager();
IWatchExpression exp1 = manager.newWatchExpression("exp1"); //$NON-NLS-1$
IWatchExpression exp2 = manager.newWatchExpression("exp2"); //$NON-NLS-1$
IWatchExpression exp3 = manager.newWatchExpression("exp3"); //$NON-NLS-1$
IWatchExpression exp4 = manager.newWatchExpression("exp4"); //$NON-NLS-1$
IWatchExpression exp5 = manager.newWatchExpression("exp5"); //$NON-NLS-1$
manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
manager.storeWatchExpressions();
// create a new manager that will restore the expressions
ExpressionManager manager2 = new ExpressionManager();
IExpression[] expressions = manager2.getExpressions();
assertEquals("Wrong number of expressions", 5, expressions.length); //$NON-NLS-1$
assertEquals("exp1", expressions[0].getExpressionText()); //$NON-NLS-1$
assertEquals("exp2", expressions[1].getExpressionText()); //$NON-NLS-1$
assertEquals("exp3", expressions[2].getExpressionText()); //$NON-NLS-1$
assertEquals("exp4", expressions[3].getExpressionText()); //$NON-NLS-1$
assertEquals("exp5", expressions[4].getExpressionText()); //$NON-NLS-1$
}
/**
* Tests concurrent access to expressions.
*
* @throws InterruptedException
*/
@Test
public void testConcurrentAccess() throws InterruptedException {
final boolean[] done = new boolean[]{false};
final Exception[] ex = new Exception[]{null};
Runnable add = () -> {
try {
for (int i = 0; i < 1000; i++) {
getManager().addExpression(getManager().newWatchExpression(Integer.toHexString(i)));
}
done[0] = true;
} catch (Exception e) {
ex[0] = e;
}
};
Runnable remove = () -> {
try {
do {
getManager().removeExpressions(getManager().getExpressions());
} while (!done[0] || getManager().getExpressions().length > 0);
} catch (Exception e) {
ex[0] = e;
}
};
Thread t1 = new Thread(add);
Thread t2 = new Thread(remove);
t1.start();
t2.start();
t1.join();
t2.join();
assertEquals(0, getManager().getExpressions().length);
assertNull(ex[0]);
}
}