diff options
author | Darin Wright | 2010-09-24 19:43:15 +0000 |
---|---|---|
committer | Darin Wright | 2010-09-24 19:43:15 +0000 |
commit | 9cabab095ea19a9d134bcb3770f5f9ebbaa8a586 (patch) | |
tree | 676494670a78f64b0c1587fcae783c7750234849 /org.eclipse.debug.tests | |
parent | 649575043f562fc67a6f5ae5767b003414180b18 (diff) | |
download | eclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.tar.gz eclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.tar.xz eclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.zip |
Bug 326063 - org.eclipse.debug.core.IExpressionManager.getExpressions() is not thread safe that it causes java.lang.ArrayIndexOutOfBoundsException
Diffstat (limited to 'org.eclipse.debug.tests')
-rw-r--r-- | org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java new file mode 100644 index 000000000..927632bcc --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java @@ -0,0 +1,569 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.tests.expressions; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +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; + +/** + * Tests expression manager and listener call backs + */ +public class ExpressionManagerTests extends TestCase { + + class SinlgeListener implements IExpressionListener { + + List added = new ArrayList(); + List removed = new ArrayList(); + List changed = new ArrayList(); + int addedCallbacks = 0; + int removedCallbacks = 0; + int changedCallbacks = 0; + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionListener#expressionAdded(org.eclipse.debug.core.model.IExpression) + */ + public void expressionAdded(IExpression expression) { + added.add(expression); + addedCallbacks++; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionListener#expressionRemoved(org.eclipse.debug.core.model.IExpression) + */ + public void expressionRemoved(IExpression expression) { + removed.add(expression); + removedCallbacks++; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionListener#expressionChanged(org.eclipse.debug.core.model.IExpression) + */ + public void expressionChanged(IExpression expression) { + changed.add(expression); + changedCallbacks++; + } + + } + + class MultiListener implements IExpressionsListener { + + List added = new ArrayList(); + List removed = new ArrayList(); + List changed = new ArrayList(); + int addedCallbacks = 0; + int removedCallbacks = 0; + int changedCallbacks = 0; + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionsListener#expressionsAdded(org.eclipse.debug.core.model.IExpression[]) + */ + public void expressionsAdded(IExpression[] expressions) { + for (int i = 0; i < expressions.length; i++) { + added.add(expressions[i]); + } + addedCallbacks++; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionsListener#expressionsRemoved(org.eclipse.debug.core.model.IExpression[]) + */ + public void expressionsRemoved(IExpression[] expressions) { + for (int i = 0; i < expressions.length; i++) { + removed.add(expressions[i]); + } + removedCallbacks++; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IExpressionsListener#expressionsChanged(org.eclipse.debug.core.model.IExpression[]) + */ + public void expressionsChanged(IExpression[] expressions) { + for (int i = 0; i < expressions.length; i++) { + changed.add(expressions[i]); + } + changedCallbacks++; + } + + } + + class InsertMoveListener extends MultiListener implements IExpressionsListener2 { + + List moved = new ArrayList(); + List inserted = new ArrayList(); + int insertIndex = -1; + int movedCallbacks = 0; + int insertedCallbacks = 0; + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.core.IExpressionsListener2#expressionsMoved(org.eclipse.debug.core.model.IExpression[], int) + */ + public void expressionsMoved(IExpression[] expressions, int index) { + for (int i = 0; i < expressions.length; i++) { + moved.add(expressions[i]); + } + movedCallbacks++; + insertIndex = index; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.core.IExpressionsListener2#expressionsInserted(org.eclipse.debug.core.model.IExpression[], int) + */ + public void expressionsInserted(IExpression[] expressions, int index) { + for (int i = 0; i < expressions.length; i++) { + inserted.add(expressions[i]); + } + insertedCallbacks++; + insertIndex = index; + } + + } + + /** + * Returns the expression manager. + * + * @return expression manager + */ + protected IExpressionManager getManager() { + return DebugPlugin.getDefault().getExpressionManager(); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + // remove all expressions from the manager + super.tearDown(); + getManager().removeExpressions(getManager().getExpressions()); + } + + /** + * 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + manager.addExpressions(new IExpression[]{exp1, exp2, exp3}); + IExpression[] expressions = manager.getExpressions(); + assertEquals("Wrong number of expressions", 3, expressions.length); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + 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); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + manager.addExpressions(new IExpression[]{exp1, exp2, exp3}); + IExpression[] expressions = manager.getExpressions(); + exp1.setEnabled(false); + exp2.setExpressionText("exp2changed"); + assertEquals("Wrong number of expressions", 3, expressions.length); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + IWatchExpression exp4 = manager.newWatchExpression("exp4"); + IWatchExpression exp5 = manager.newWatchExpression("exp5"); + manager.addExpressions(new IExpression[]{exp1, exp2, exp3}); + IExpression[] expressions = manager.getExpressions(); + assertEquals("Wrong number of expressions", 3, expressions.length); + 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); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + IWatchExpression exp4 = manager.newWatchExpression("exp4"); + IWatchExpression exp5 = manager.newWatchExpression("exp5"); + manager.addExpressions(new IExpression[]{exp1, exp2, exp3}); + IExpression[] expressions = manager.getExpressions(); + assertEquals("Wrong number of expressions", 3, expressions.length); + 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); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + IWatchExpression exp4 = manager.newWatchExpression("exp4"); + IWatchExpression exp5 = manager.newWatchExpression("exp5"); + 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); + 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. + */ + 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"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + IWatchExpression exp4 = manager.newWatchExpression("exp4"); + IWatchExpression exp5 = manager.newWatchExpression("exp5"); + 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); + 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 + */ + public void testPersistExpressions() { + ExpressionManager manager = (ExpressionManager) getManager(); + IWatchExpression exp1 = manager.newWatchExpression("exp1"); + IWatchExpression exp2 = manager.newWatchExpression("exp2"); + IWatchExpression exp3 = manager.newWatchExpression("exp3"); + IWatchExpression exp4 = manager.newWatchExpression("exp4"); + IWatchExpression exp5 = manager.newWatchExpression("exp5"); + 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); + assertEquals("exp1", expressions[0].getExpressionText()); + assertEquals("exp2", expressions[1].getExpressionText()); + assertEquals("exp3", expressions[2].getExpressionText()); + assertEquals("exp4", expressions[3].getExpressionText()); + assertEquals("exp5", expressions[4].getExpressionText()); + } + + /** + * Tests concurrent access to expressions. + * + * @throws InterruptedException + */ + public void testConcurrentAccess() throws InterruptedException { + final boolean[] done = new boolean[]{false}; + final Exception[] ex = new Exception[]{null}; + Runnable add = new Runnable() { + public void run() { + 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 = new Runnable() { + public void run() { + 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]); + } + +} |