aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Elder2013-04-25 10:51:32 (EDT)
committerPaul Elder2013-04-26 13:53:29 (EDT)
commit14df8707c0e630165fb4ef55f648f29e4798189b (patch)
tree499adfb3e93b52c9397b0cdee1470038758e1fe1
parent2002e9a0bd9fa578004cc1b762118b8fc60dbcdb (diff)
downloadeclipse.platform.runtime-14df8707c0e630165fb4ef55f648f29e4798189b.zip
eclipse.platform.runtime-14df8707c0e630165fb4ef55f648f29e4798189b.tar.gz
eclipse.platform.runtime-14df8707c0e630165fb4ef55f648f29e4798189b.tar.bz2
Bug 406355: EclipseContext re-runs RunAndTrack's on changes that cannotI20130429-0800I20130428-2000refs/changes/07/12207/2
be seen by the RunAndTrack * contribute 12 new unit tests cover expected RAT execution behavior * fix ActivationTest.testGetActiveRATNumberOfCalls() (broken with fix to bug 394336) * change EclipseContext to not invalidate RATs in child contexts if the changed or removed variable is redefined in that child context, regardless of the value of the changed variable. Change-Id: Ib0b13d95d88e87ac635a46527391c957c800ca3e
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java10
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ActivationTest.java61
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/RunAndTrackTest.java233
3 files changed, 295 insertions, 9 deletions
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
index 6f56963..1f9256f 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2012 IBM Corporation and others.
+ * Copyright (c) 2009, 2013 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
@@ -277,8 +277,8 @@ public class EclipseContext implements IEclipseContext {
// invalidate this name in child contexts
for (EclipseContext childContext : getChildren()) {
- // unless it is already set to the same value
- if (eventType == ContextChangeEvent.ADDED && childContext.isLocalEquals(name, newValue))
+ // unless it is already set in this context (and thus hides the change)
+ if ((eventType == ContextChangeEvent.ADDED || eventType == ContextChangeEvent.REMOVED) && childContext.isSetLocally(name))
continue;
childContext.invalidate(name, eventType, oldValue, newValue, scheduled);
}
@@ -336,7 +336,7 @@ public class EclipseContext implements IEclipseContext {
}
boolean containsKey = localValues.containsKey(name);
Object oldValue = localValues.put(name, value);
- if (!containsKey || value != oldValue) {
+ if (!containsKey || oldValue != value) {
Set<Scheduled> scheduled = new LinkedHashSet<Scheduled>();
invalidate(name, ContextChangeEvent.ADDED, oldValue, value, scheduled);
processScheduled(scheduled);
@@ -370,7 +370,7 @@ public class EclipseContext implements IEclipseContext {
throw new IllegalArgumentException(tmp);
}
Object oldValue = localValues.put(name, value);
- if (value != oldValue)
+ if (oldValue != value)
invalidate(name, ContextChangeEvent.ADDED, oldValue, value, scheduled);
return true;
}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ActivationTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ActivationTest.java
index 184aef7..d8fbd7b 100644
--- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ActivationTest.java
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ActivationTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
+ * Copyright (c) 2010, 2013 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
@@ -238,15 +238,70 @@ public class ActivationTest extends TestCase {
child12.activateBranch();
assertEquals("1", result[0]);
- assertEquals(2, called[0]);
+ assertEquals(3, called[0]);
child22.activateBranch();
assertEquals("1", result[0]);
- assertEquals(2, called[0]);
+ assertEquals(3, called[0]);
child21.activateBranch();
assertEquals("1", result[0]);
+ assertEquals(3, called[0]);
+ }
+
+ /**
+ * A variation of {@link #testGetActiveRATNumberOfCalls()} that
+ * uses distinct values in the leaf contexts.
+ */
+ public void testGetActiveRATNumberOfCalls2() {
+ IEclipseContext root = EclipseContextFactory.create("root");
+
+ IEclipseContext child1 = root.createChild("child1");
+ IEclipseContext child11 = child1.createChild("child11");
+ IEclipseContext child12 = child1.createChild("child12");
+
+ IEclipseContext child2 = root.createChild("child2");
+ IEclipseContext child21 = child2.createChild("child21");
+ IEclipseContext child22 = child2.createChild("child22");
+
+ child11.set("var", "11");
+ child12.set("var", "12");
+ child1.set("var", "3");
+ child21.set("var", "21");
+ child22.set("var", "22");
+ child2.set("var", "6");
+ root.set("var", "7");
+
+ final String[] result = new String[1];
+ final int[] called = new int[1];
+ called[0] = 0;
+
+ child1.runAndTrack(new RunAndTrack() {
+ public boolean changed(IEclipseContext context) {
+ result[0] = (String) context.getActive("var");
+ called[0]++;
+ return true;
+ }});
+
+ // nothing is active - we get value from the node
+ assertEquals("3", result[0]);
+ assertEquals(1, called[0]);
+
+ child11.activateBranch();
+ assertEquals("11", result[0]);
assertEquals(2, called[0]);
+
+ child12.activateBranch();
+ assertEquals("12", result[0]);
+ assertEquals(3, called[0]);
+
+ child22.activateBranch();
+ assertEquals("12", result[0]);
+ assertEquals(3, called[0]);
+
+ child21.activateBranch();
+ assertEquals("12", result[0]);
+ assertEquals(3, called[0]);
}
public static class ActiveInject {
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/RunAndTrackTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/RunAndTrackTest.java
index a19376f..0b6d72b 100644
--- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/RunAndTrackTest.java
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/RunAndTrackTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2013 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
@@ -27,6 +27,38 @@ import org.eclipse.e4.core.internal.tests.CoreTestsActivator;
* Tests for {@link org.eclipse.e4.core.RunAndTrack.context.IRunAndTrack}.
*/
public class RunAndTrackTest extends TestCase {
+
+ private static final class TestRAT extends RunAndTrack {
+
+
+ private String varName;
+ private Object varValue;
+ private int calls = 0;
+
+ public TestRAT(String varName) {
+ this.varName = varName;
+ }
+
+ @Override
+ public boolean changed(IEclipseContext context) {
+ ++calls;
+ varValue = context.get(varName);
+ return true;
+ }
+
+ public int getCalls() {
+ return calls;
+ }
+
+ public Object getVarValue() {
+ return varValue;
+ }
+
+ public void resetCalls() {
+ calls = 0;
+ }
+
+ }
private class ActivePartLookupFunction extends ContextFunction {
@@ -196,4 +228,203 @@ public class RunAndTrackTest extends TestCase {
assertEquals("part1", windows[0].get(ACTIVE_PART));
assertEquals("part1", windows[0].get(ACTIVE_PART_ID));
}
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is == to child value
+ */
+ public void testSetHiddenValueToChildObject() {
+ final String newRootValue = "child";
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is != to child value
+ */
+ public void testSetHiddenValueToDifferentObject() {
+ final String newRootValue = "other";
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is != to child value (but is .equals())
+ */
+ public void testSetHiddenValueToObjectEqualToChild() {
+ // avoid compiler's pushing all my strings into a single string pool
+ final String newRootValue = new String("child");
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is == to root value
+ */
+ public void testSetHiddenValueToRootObject() {
+ final String newRootValue = "root";
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is != to root value (but is .equals())
+ */
+ public void testSetHiddenValueToEqualRootObject() {
+ // avoid compiler's pushing all my strings into a single string pool
+ final String newRootValue = new String("root");
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Test how a RAT responds to a change hidden from it; changed value is == to root value
+ */
+ public void testSetHiddenValueToNull() {
+ final String newRootValue = null;
+
+ doHiddenValueChangeTest(newRootValue);
+ }
+
+ /**
+ * Perform a hidden value test that verifies that the test RAT does not run, and
+ * that has last seen the initial value in the child context (namely "child").
+ * @param newRootValue the new value for the variable 'v' in the root context.
+ * @see #doHiddenValueChangeTest(ITestAction, Object, int)
+ */
+ void doHiddenValueChangeTest(final String newRootValue) {
+ doHiddenValueChangeTest(new ITestAction() {
+
+ public void execute(IEclipseContext root, String var) {
+ root.set(var, newRootValue);
+
+ }
+ }, "child", 0);
+ }
+
+ /**
+ * Interface defining function
+ *
+ */
+ private interface ITestAction {
+
+ void execute(IEclipseContext root, String var);
+
+ }
+ /**
+ * Create a two level hierarchy of contexts, each defining a variable 'v' with values 'root' and 'child', respectively.
+ * Create and install a RAT on the child context that is dependent on 'v'.
+ * Run <code>testAction</code>.
+ * Tests whether the RAT ran the expected number of times,
+ * and tests last value of 'v' that the RAT saw.
+ * @param testAction the context action to perform as part of the test
+ * @param expectedValue the expected last value of variable 'v' that the RAT saw.
+ * @param expectedRATCalls the expected number of times the RAT was run in response to testAction
+ */
+ void doHiddenValueChangeTest(ITestAction testAction, Object expectedValue, int expectedRATCalls) {
+ final IEclipseContext root = getGlobalContext();
+ final IEclipseContext child = root.createChild("child");
+
+ root.set("v", "root");
+ child.set("v", "child");
+ final TestRAT testRAT = new TestRAT("v");
+
+ // install the RAT
+ child.runAndTrack(testRAT);
+ assertEquals("child", testRAT.getVarValue());
+ assertEquals(1, testRAT.getCalls());
+
+ testRAT.resetCalls();
+ // set the new root value
+ testAction.execute(root, "v");
+ assertEquals(expectedValue, testRAT.getVarValue());
+ assertEquals(expectedRATCalls, testRAT.getCalls());
+ }
+
+ /**
+ * Test that a variable change in a context hidden from a RAT in
+ * a child context does not re-run the RAT.
+ */
+ public void testRemoveHiddenVariable() {
+ doHiddenValueChangeTest(new ITestAction() {
+
+ public void execute(IEclipseContext root, String var) {
+ root.remove(var);;
+
+ }
+ }, "child", 0);
+ }
+
+ /**
+ * Test that setting a context variable to it's existing
+ * value does not re-run dependent RATs
+ */
+ public void testSetContextVarToSameObject() {
+ doSingleContextChangeTest(new ITestAction() {
+ public void execute(IEclipseContext root, String var) {
+ root.set(var, "root");
+ }
+ }, "root", 0);
+ }
+
+ /**
+ * Test that setting a context variable to a value that {@link Object#equals(Object) equals}
+ * the current value, but is same object DOES re-run dependent RATs.
+ */
+ public void testSetContextVarToEqualObject() {
+ doSingleContextChangeTest(new ITestAction() {
+ public void execute(IEclipseContext root, String var) {
+ root.set(var, new String("root"));
+ }
+ }, "root", 1);
+ }
+
+ /**
+ * Test that setting a context variable to a different object, not equal to the
+ * current value re-runs dependent RATs.
+ */
+ public void testSetContextVarToOtherObject() {
+ doSingleContextChangeTest(new ITestAction() {
+ public void execute(IEclipseContext root, String var) {
+ root.set(var, "other");
+ }
+ }, "other", 1);
+ }
+
+ /**
+ * Test that removing a context variable re-runs dependent RATs.
+ */
+ public void testRemoveContextVar() {
+ doSingleContextChangeTest(new ITestAction() {
+ public void execute(IEclipseContext root, String var) {
+ root.remove(var);
+ }
+ }, null, 1);
+
+ }
+
+ /**
+ * Creates a context, sets a variable 'v' to "root", creates a RAT dependent on 'v' in the context,
+ * then executes <code>testAction</code> and tests whether the RAT ran the expected number of times,
+ * and tests last value of 'v' that the RAT saw.
+ * @param testAction the context action to perform as part of the test
+ * @param expectedValue the expected last value of variable 'v' that the RAT saw.
+ * @param expectedRATCalls the expected number of times the RAT was run in response to testAction
+ */
+ private void doSingleContextChangeTest(ITestAction testAction, Object expectedValue, int expectedRATCalls) {
+ final IEclipseContext root = getGlobalContext();
+
+ root.set("v", "root");
+
+ final TestRAT testRAT = new TestRAT("v");
+ // install the RAT
+ root.runAndTrack(testRAT);
+ assertEquals("root", testRAT.getVarValue());
+ assertEquals(1, testRAT.getCalls());
+
+ testRAT.resetCalls();
+ testAction.execute(root, "v");
+ assertEquals(expectedRATCalls, testRAT.getCalls());
+ assertEquals(expectedValue, testRAT.getVarValue());
+
+ }
}