### Eclipse Workspace Patch 1.0
#P org.eclipse.jface.tests.databinding
Index: src/org/eclipse/core/tests/databinding/observable/value/WritableValueTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/observable/value/WritableValueTest.java,v
retrieving revision 1.1
diff -u -r1.1 WritableValueTest.java
--- src/org/eclipse/core/tests/databinding/observable/value/WritableValueTest.java 14 Apr 2007 20:46:38 -0000 1.1
+++ src/org/eclipse/core/tests/databinding/observable/value/WritableValueTest.java 15 Jul 2007 05:04:55 -0000
@@ -12,11 +12,18 @@
package org.eclipse.core.tests.databinding.observable.value;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.jface.conformance.databinding.AbstractObservableValueContractDelegate;
+import org.eclipse.jface.conformance.databinding.ObservableValueContractTests;
+import org.eclipse.jface.conformance.databinding.SuiteBuilder;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
-import org.eclipse.jface.tests.databinding.EventTrackers.ValueChangeEventTracker;
import org.eclipse.swt.widgets.Display;
/**
@@ -24,42 +31,6 @@
*/
public class WritableValueTest extends AbstractDefaultRealmTestCase {
/**
- * Asserts that ValueChange events are only fired when the value changes.
- *
- * @throws Exception
- */
- public void testValueChangeOnlyFiresOnChange() throws Exception {
- WritableValue writableValue = new WritableValue();
- ValueChangeEventTracker counter = new ValueChangeEventTracker();
- writableValue.addValueChangeListener(counter);
-
- assertEquals(0, counter.count);
- // set same
- writableValue.setValue(null);
- assertEquals(0, counter.count);
-
- // set different
- writableValue.setValue("value");
- assertEquals(1, counter.count);
-
- // set same
- writableValue.setValue("value");
- assertEquals(1, counter.count);
-
- // set different
- writableValue.setValue(null);
- assertEquals(2, counter.count);
- }
-
- public void testDoSetValue() throws Exception {
- WritableValue writableValue = new WritableValue(SWTObservables
- .getRealm(Display.getDefault()));
- Object value = new Object();
- writableValue.setValue(value);
- assertEquals(value, writableValue.getValue());
- }
-
- /**
* All constructors delegate to the 3 arg constructor.
*
* @throws Exception
@@ -70,7 +41,7 @@
assertNull(value.getValue());
assertNull(value.getValueType());
}
-
+
public void testWithValueType() throws Exception {
Object elementType = String.class;
WritableValue value = WritableValue.withValueType(elementType);
@@ -78,4 +49,39 @@
assertEquals(Realm.getDefault(), value.getRealm());
assertEquals(elementType, value.getValueType());
}
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ Object[] params = new Object[] { new Delegate() };
+
+ SuiteBuilder
+ .forSuite(suite)
+ .addTests(WritableValueTest.class)
+ .addParameterizedTests(ObservableValueContractTests.class, params);
+
+ return suite;
+ }
+
+ /* package */ static class Delegate extends AbstractObservableValueContractDelegate {
+ private WritableValue current;
+
+ public IObservableValue createObservableValue() {
+ Realm.runWithDefault(SWTObservables.getRealm(Display.getDefault()), new Runnable() {
+ public void run() {
+ current = new WritableValue("", String.class);
+ }
+ });
+
+ return current;
+ }
+
+ public void change(IObservable observable) {
+ WritableValue writableValue = (WritableValue) observable;
+ writableValue.setValue(writableValue.getValue() + "a");
+ }
+
+ public Object getValueType(IObservableValue observable) {
+ return String.class;
+ }
+ }
}
Index: src/org/eclipse/core/tests/databinding/observable/AbstractObservableTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/observable/AbstractObservableTest.java,v
retrieving revision 1.1
diff -u -r1.1 AbstractObservableTest.java
--- src/org/eclipse/core/tests/databinding/observable/AbstractObservableTest.java 14 Apr 2007 20:46:40 -0000 1.1
+++ src/org/eclipse/core/tests/databinding/observable/AbstractObservableTest.java 15 Jul 2007 05:04:55 -0000
@@ -12,6 +12,9 @@
package org.eclipse.core.tests.databinding.observable;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
import org.eclipse.core.databinding.observable.AbstractObservable;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
@@ -19,9 +22,15 @@
import org.eclipse.core.databinding.observable.IStaleListener;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.StaleEvent;
+import org.eclipse.jface.conformance.databinding.AbstractObservableContractDelegate;
+import org.eclipse.jface.conformance.databinding.ObservableContractTests;
+import org.eclipse.jface.conformance.databinding.ObservableStaleContractTests;
+import org.eclipse.jface.conformance.databinding.SuiteBuilder;
+import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
import org.eclipse.jface.tests.databinding.RealmTester;
import org.eclipse.jface.tests.databinding.RealmTester.CurrentRealm;
+import org.eclipse.swt.widgets.Display;
/**
* Tests for AbstractObservable.
@@ -187,6 +196,7 @@
private class ChangeListener implements IChangeListener {
int count;
+
IObservable source;
public void handleChange(ChangeEvent event) {
@@ -197,6 +207,7 @@
private class StaleListener implements IStaleListener {
int count;
+
IObservable source;
public void handleStale(StaleEvent event) {
@@ -205,7 +216,47 @@
}
}
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ Object[] params = new Object[] { new Delegate() };
+
+ SuiteBuilder
+ .forSuite(suite)
+ .addTests(AbstractObservableTest.class)
+ .addParameterizedTests(ObservableContractTests.class, params)
+ .addParameterizedTests(ObservableStaleContractTests.class,
+ params);
+
+ return suite;
+ }
+
+ /* package */static class Delegate extends
+ AbstractObservableContractDelegate {
+ private IObservable currentObservable;
+
+ public void change(IObservable observable) {
+ ((ObservableStub) observable).fireChange();
+ }
+
+ public void setStale(IObservable observable, boolean stale) {
+ ((ObservableStub) observable).setStale(stale);
+ }
+
+ public IObservable createObservable() {
+ Realm.runWithDefault(SWTObservables.getRealm(Display.getDefault()),
+ new Runnable() {
+ public void run() {
+ currentObservable = new ObservableStub();
+ }
+ });
+
+ return currentObservable;
+ }
+ }
+
private static class ObservableStub extends AbstractObservable {
+ private boolean stale;
+
public ObservableStub() {
this(Realm.getDefault());
}
@@ -218,6 +269,7 @@
}
private boolean firstListenerAdded;
+
private boolean lastListenerRemoved;
protected Object doGetValue() {
@@ -237,7 +289,16 @@
}
public boolean isStale() {
- return false;
+ return stale;
+ }
+
+ public void setStale(boolean stale) {
+ boolean old = this.stale;
+ this.stale = stale;
+
+ if (stale && !old) {
+ fireStale();
+ }
}
protected boolean hasListeners() {
Index: src/org/eclipse/jface/tests/internal/databinding/internal/swt/ButtonObservableValueTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/internal/databinding/internal/swt/ButtonObservableValueTest.java,v
retrieving revision 1.1
diff -u -r1.1 ButtonObservableValueTest.java
--- src/org/eclipse/jface/tests/internal/databinding/internal/swt/ButtonObservableValueTest.java 4 Dec 2006 15:50:09 -0000 1.1
+++ src/org/eclipse/jface/tests/internal/databinding/internal/swt/ButtonObservableValueTest.java 15 Jul 2007 05:04:55 -0000
@@ -11,8 +11,15 @@
package org.eclipse.jface.tests.internal.databinding.internal.swt;
+import junit.framework.Test;
import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.jface.conformance.databinding.AbstractObservableValueContractDelegate;
+import org.eclipse.jface.conformance.databinding.ObservableValueContractTests;
+import org.eclipse.jface.conformance.databinding.SuiteBuilder;
import org.eclipse.jface.internal.databinding.internal.swt.ButtonObservableValue;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
@@ -20,20 +27,47 @@
/**
* @since 3.2
- *
*/
-public class ButtonObservableValueTest extends TestCase {
- public void testSetValue() throws Exception {
- Shell shell = new Shell();
- Button button = new Button(shell, SWT.CHECK);
- ButtonObservableValue observableValue = new ButtonObservableValue(button);
- assertEquals(Boolean.FALSE, observableValue.getValue());
- assertFalse(button.getSelection());
-
- Boolean value = Boolean.TRUE;
- observableValue.setValue(value);
- assertTrue("button value", button.getSelection());
- assertEquals("observable value", value, observableValue.getValue());
- shell.dispose();
+public class ButtonObservableValueTest extends TestCase {
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ Object[] params = new Object[] { new Delegate() };
+
+ SuiteBuilder
+ .forSuite(suite)
+ .addParameterizedTests(ObservableValueContractTests.class, params);
+
+ return suite;
+ }
+
+ /* package */ static class Delegate extends AbstractObservableValueContractDelegate {
+ Shell shell;
+ Button button;
+
+ public void setUp() {
+ super.setUp();
+
+ shell = new Shell();
+ button = new Button(shell, SWT.CHECK);
+ }
+
+ public void tearDown() {
+ super.tearDown();
+
+ shell.dispose();
+ }
+
+ public IObservableValue createObservableValue() {
+ return new ButtonObservableValue(button);
+ }
+
+ public Object getValueType(IObservableValue observable) {
+ return Boolean.TYPE;
+ }
+
+ public void change(IObservable observable) {
+ button.setSelection(!button.getSelection());
+ button.notifyListeners(SWT.Selection, null);
+ }
}
}
Index: src/org/eclipse/jface/tests/databinding/BindingTestSuite.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java,v
retrieving revision 1.53
diff -u -r1.53 BindingTestSuite.java
--- src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 4 Jul 2007 20:08:44 -0000 1.53
+++ src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 15 Jul 2007 05:04:55 -0000
@@ -147,7 +147,7 @@
addTestSuite(StringToNumberConverterTest.class);
// org.eclipse.core.tests.databinding.observable
- addTestSuite(AbstractObservableTest.class);
+ addTest(AbstractObservableTest.suite());
addTestSuite(Diffs_ListDiffTests.class);
addTestSuite(DiffsTest.class);
addTestSuite(ObservablesTest.class);
@@ -174,7 +174,8 @@
addTestSuite(AbstractObservableValueTest.class);
addTestSuite(AbstractVetoableValueTest.class);
addTestSuite(ComputedValueTest.class);
- addTestSuite(WritableValueTest.class);
+ addTest(WritableValueTest.suite());
+// addTestSuite(WritableValueTest.class);
//org.eclipse.core.tests.databinding.validation
addTestSuite(ValidationStatusTest.class);
@@ -261,7 +262,8 @@
addTestSuite(EditMaskParserTest.class);
//org.eclipse.jface.tests.internal.databinding.internal.swt
- addTestSuite(ButtonObservableValueTest.class);
+ addTest(ButtonObservableValueTest.suite());
+// addTestSuite(ButtonObservableValueTest.class);
addTestSuite(CComboObservableValueTest.class);
addTestSuite(CLabelObservableValueTest.class);
addTestSuite(ComboObservableValueTest.class);
Index: src/org/eclipse/jface/conformance/databinding/SuiteBuilder.java
===================================================================
RCS file: src/org/eclipse/jface/conformance/databinding/SuiteBuilder.java
diff -N src/org/eclipse/jface/conformance/databinding/SuiteBuilder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/conformance/databinding/SuiteBuilder.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Brad Reynolds 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:
+ * Brad Reynolds - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.jface.conformance.databinding;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Builds a test suite.
+ *
+ * @since 1.1
+ */
+// TODO remove the forSuite(...) method and add a toSuite() method that returns
+// a new TestSuite.
+public class SuiteBuilder {
+ private TestSuite suite;
+
+ private SuiteBuilder(TestSuite suite) {
+ // prohibit public construction
+ this.suite = suite;
+ }
+
+ /**
+ * Adds all test methods from the provided testCase
to the
+ * suite.
+ *
+ * @param testCase
+ * @return builder
+ */
+ public SuiteBuilder addTests(Class testCase) {
+ suite.addTestSuite(testCase);
+ return this;
+ }
+
+ /**
+ * Adds all test methods from the provided testCase
with the
+ * provided parameters
. A constructor must exist in the
+ * testCase that accepts a String as the first parameter followed by
+ * parameters matching the provided parameters. If an appropriate
+ * constructor is not found an exception will be thrown.
+ *
+ * @param testCase
+ * @param parameters
+ * @return builder
+ */
+ public SuiteBuilder addParameterizedTests(Class testCase,
+ Object[] parameters) {
+ Method[] methods = testCase.getMethods();
+
+ Constructor constructor = findConstructor(testCase, parameters);
+ if (constructor == null) {
+ throw new IllegalArgumentException(
+ "The parameters provided don't match a constructor found in ["
+ + testCase.getName() + "]");
+ }
+
+ for (int i = 0; i < methods.length; i++) {
+ String name = methods[i].getName();
+ if (name.startsWith("test")) {
+ try {
+ suite.addTest((Test) constructor.newInstance(toParamArray(
+ name, parameters)));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ return this;
+ }
+
+ private Object[] toParamArray(String testName, Object[] parameters) {
+ Object[] result = new Object[parameters.length + 1];
+ result[0] = testName;
+ System.arraycopy(parameters, 0, result, 1, parameters.length);
+ return result;
+ }
+
+ /**
+ * Returns the constructor that has a String as the first parameters and
+ * then matches the type of the parameters.
+ *
+ * @param parameters
+ * @return
+ */
+ private static Constructor findConstructor(Class clazz, Object[] parameters) {
+ Constructor[] constructors = clazz.getConstructors();
+ int expectedParametersLength = parameters.length + 1;
+
+ for (int i = 0; i < constructors.length; i++) {
+ Constructor constructor = constructors[i];
+ Class[] types = constructor.getParameterTypes();
+
+ if (types.length != expectedParametersLength
+ || !String.class.equals(types[i])) {
+ continue;
+ }
+
+ boolean skip = false;
+ for (int j = 1; j < types.length; j++) {
+ Class type = types[j];
+ if (!type.isInstance(parameters[j - 1])) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (!skip) {
+ return constructor;
+ }
+ }
+
+ return null;
+ }
+
+ public static SuiteBuilder forSuite(TestSuite suite) {
+ return new SuiteBuilder(suite);
+ }
+
+ /* package */static class UniqueTest {
+ /* package */UniqueTest(Class clazz, String testName,
+ Object[] parameters) {
+
+ }
+ }
+}
Index: src/org/eclipse/jface/conformance/databinding/ObservableStaleContractTests.java
===================================================================
RCS file: src/org/eclipse/jface/conformance/databinding/ObservableStaleContractTests.java
diff -N src/org/eclipse/jface/conformance/databinding/ObservableStaleContractTests.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/conformance/databinding/ObservableStaleContractTests.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Brad Reynolds 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:
+ * Brad Reynolds - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.jface.conformance.databinding;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.IStaleListener;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.StaleEvent;
+import org.eclipse.jface.conformance.databinding.ObservableContractTests.DummyRealm;
+
+/**
+ * @since 3.3
+ */
+public class ObservableStaleContractTests extends TestCase {
+ private IObservableContractDelegate delegate;
+ private Realm previousRealm;
+
+ public ObservableStaleContractTests(String testName, IObservableContractDelegate delegate) {
+ super(testName);
+ this.delegate = delegate;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ previousRealm = Realm.getDefault();
+ delegate.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ delegate.tearDown();
+ DummyRealm.setDefaultRealm(previousRealm);
+ }
+
+ public void testIsStaleReturnsTrueWhenStale() throws Exception {
+ IObservable observable = delegate.createObservable();
+ delegate.setStale(observable, true);
+ assertTrue("When stale isStale() should return true.", observable.isStale());
+ }
+
+ public void testIsStaleReturnsFalseWhenNotStale() throws Exception {
+ IObservable observable = delegate.createObservable();
+ delegate.setStale(observable, false);
+ assertFalse("When not stale isStale() should return false.", observable.isStale());
+ }
+
+ public void testBecomingStaleFiresStaleEvent() throws Exception {
+ IObservable observable = delegate.createObservable();
+ StaleListener listener = new StaleListener();
+
+ // precondition
+ ensureStale(observable, false);
+
+ observable.addStaleListener(listener);
+ delegate.setStale(observable, true);
+
+ assertEquals("When becoming stale listeners should be notified.", 1, listener.count);
+ }
+
+ public void testStaleEventObservable() throws Exception {
+ IObservable observable = delegate.createObservable();
+ StaleListener listener = new StaleListener();
+
+ // precondition
+ ensureStale(observable, false);
+
+ observable.addStaleListener(listener);
+ delegate.setStale(observable, true);
+
+ StaleEvent event = listener.event;
+ assertNotNull("stale event was null", event);
+ assertEquals("When notifying listeners of becoming stale the observable should be the source of the event.", observable,
+ event.getObservable());
+ }
+
+ public void testRemoveStaleListenerRemovesListener() throws Exception {
+ StaleListener listener = new StaleListener();
+ IObservable observable = delegate.createObservable();
+
+ observable.addStaleListener(listener);
+ ensureStale(observable, false);
+ delegate.setStale(observable, true);
+
+ // precondition check
+ assertEquals("set stale did not notify listeners", 1, listener.count);
+
+ observable.removeStaleListener(listener);
+ ensureStale(observable, false);
+ delegate.setStale(observable, true);
+
+ assertEquals("Once removed stale listeners should not be notified of becoming stale.", 1,
+ listener.count);
+ }
+
+ public void testStaleListenersAreNotNotifiedWhenObservableIsNoLongerStale()
+ throws Exception {
+ IObservable observable = delegate.createObservable();
+ ensureStale(observable, true);
+
+ StaleListener listener = new StaleListener();
+ observable.addStaleListener(listener);
+ delegate.setStale(observable, false);
+
+ assertEquals("Stale listeners should not be notified when the stale state changes from true to false.", 0,
+ listener.count);
+ }
+
+ public void testObservableRealmIsCurrentOnStale() throws Exception {
+ IObservable observable = delegate.createObservable();
+ ensureStale(observable, false);
+
+ StaleListener listener = new StaleListener();
+ observable.addStaleListener(listener);
+ delegate.setStale(observable, true);
+
+ assertTrue("When notifying listeners of becoming stale the observable's realm should be the current realm.",
+ listener.isCurrentRealm);
+ }
+
+ /**
+ * Ensures that stale is set to the provided state. Will throw an
+ * AssertionFailedError if setting of the state is unsuccessful.
+ *
+ * @param observable
+ * @param stale
+ */
+ private void ensureStale(IObservable observable, boolean stale) {
+ if (observable.isStale() != stale) {
+ delegate.setStale(observable, stale);
+ }
+
+ assertEquals(stale, observable.isStale());
+ }
+
+ /* package */static class StaleListener implements IStaleListener {
+ int count;
+
+ StaleEvent event;
+
+ boolean isCurrentRealm;
+
+ public void handleStale(StaleEvent staleEvent) {
+ count++;
+ this.event = staleEvent;
+ this.isCurrentRealm = staleEvent.getObservable().getRealm()
+ .isCurrent();
+ }
+ }
+
+}
Index: src/org/eclipse/jface/conformance/databinding/ObservableContractTests.java
===================================================================
RCS file: src/org/eclipse/jface/conformance/databinding/ObservableContractTests.java
diff -N src/org/eclipse/jface/conformance/databinding/ObservableContractTests.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/conformance/databinding/ObservableContractTests.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Brad Reynolds 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:
+ * Brad Reynolds - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.jface.conformance.databinding;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.databinding.observable.ChangeEvent;
+import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.Realm;
+
+/**
+ * TestCase that asserts the conformance of an observable to the defined
+ * contract for changes.
+ *
+ * @since 3.2
+ */
+public class ObservableContractTests extends TestCase {
+ private Realm previousRealm;
+
+ private IObservableContractDelegate delegate;
+
+ public ObservableContractTests(IObservableContractDelegate delegate) {
+ super();
+
+ this.delegate = delegate;
+ }
+
+ public ObservableContractTests(String testName,
+ IObservableContractDelegate delegate) {
+ super(testName);
+ this.delegate = delegate;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ previousRealm = Realm.getDefault();
+ delegate.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ delegate.tearDown();
+ DummyRealm.setDefaultRealm(previousRealm);
+ }
+
+ public void testRealmIsNotNull() throws Exception {
+ IObservable observable = delegate.createObservable();
+
+ assertNotNull("The observable's realm should not be null.", observable.getRealm());
+ }
+
+ public void testChangeFiresChangeEvent() throws Exception {
+ ChangeListener listener = new ChangeListener();
+ IObservable observable = delegate.createObservable();
+
+ observable.addChangeListener(listener);
+ delegate.change(observable);
+
+ assertEquals("A change in the observable should notify change listeners.", listener.count, 1);
+ }
+
+ public void testChangeEventObservable() throws Exception {
+ ChangeListener listener = new ChangeListener();
+ IObservable observable = delegate.createObservable();
+
+ observable.addChangeListener(listener);
+ delegate.change(observable);
+
+ ChangeEvent event = listener.event;
+ assertNotNull("change event was null", event);
+
+ assertSame("In the change event the source of the change should be the observable.", observable,
+ event.getObservable());
+ }
+
+ public void testObservableRealmIsTheCurrentRealmOnChange() throws Exception {
+ IObservable observable = delegate.createObservable();
+ ChangeListener listener = new ChangeListener();
+ observable.addChangeListener(listener);
+
+ delegate.change(observable);
+ assertTrue("On change the current realm should be the realm of the observable.",
+ listener.isCurrentRealm);
+ }
+
+ public void testRemoveChangeListenerRemovesListener() throws Exception {
+ ChangeListener listener = new ChangeListener();
+ IObservable observable = delegate.createObservable();
+
+ observable.addChangeListener(listener);
+ delegate.change(observable);
+
+ // precondition check
+ assertEquals("change did not notify listeners", 1, listener.count);
+
+ observable.removeChangeListener(listener);
+ delegate.change(observable);
+
+ assertEquals("When a change listener is removed it should not still receive change events.", 1,
+ listener.count);
+ }
+
+ public void testIsNotStale() throws Exception {
+ IObservable observable = delegate.createObservable();
+
+ delegate.setStale(observable, false);
+ assertFalse("When an observable is not stale isStale() should return false.", observable.isStale());
+ }
+
+ /**
+ * Workaround to be able to set the default realm outside a runnable. The
+ * setDefaultRealm(...) method is the only usable method.
+ *
+ * @since 3.2
+ */
+ /* package */static class DummyRealm extends Realm {
+ /**
+ * Can't be instantiated.
+ */
+ private DummyRealm() {
+ }
+
+ static void setDefaultRealm(Realm realm) {
+ setDefault(realm);
+ }
+
+ public boolean isCurrent() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /* package */static class ChangeListener implements IChangeListener {
+ int count;
+
+ ChangeEvent event;
+
+ boolean isCurrentRealm;
+
+ public void handleChange(ChangeEvent event) {
+ count++;
+ this.event = event;
+ this.isCurrentRealm = event.getObservable().getRealm().isCurrent();
+ }
+ }
+}
Index: src/org/eclipse/jface/conformance/databinding/AbstractObservableValueContractDelegate.java
===================================================================
RCS file: src/org/eclipse/jface/conformance/databinding/AbstractObservableValueContractDelegate.java
diff -N src/org/eclipse/jface/conformance/databinding/AbstractObservableValueContractDelegate.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/conformance/databinding/AbstractObservableValueContractDelegate.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Brad Reynolds 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:
+ * Brad Reynolds - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.jface.conformance.databinding;
+
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+
+/**
+ * Abstract implementation of {@link IObservableValueContractDelegate}.
+ *
+ * @since 1.1
+ */
+public abstract class AbstractObservableValueContractDelegate extends
+ AbstractObservableContractDelegate implements
+ IObservableValueContractDelegate {
+
+ /**
+ * Invokes {@link #createObservableValue()}.
+ */
+ public final IObservable createObservable() {
+ return createObservableValue();
+ }
+
+ /**
+ * Default implementation returns null
.
+ */
+ public Object getValueType(IObservableValue observable) {
+ // no op
+ return null;
+ }
+}
Index: src/org/eclipse/jface/conformance/databinding/IObservableValueContractDelegate.java
===================================================================
RCS file: src/org/eclipse/jface/conformance/databinding/IObservableValueContractDelegate.java
diff -N src/org/eclipse/jface/conformance/databinding/IObservableValueContractDelegate.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/conformance/databinding/IObservableValueContractDelegate.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Brad Reynolds 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:
+ * Brad Reynolds - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.jface.conformance.databinding;
+
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+
+/**
+ * Delegate interface for an observable value.
+ *
+ *
+ * Do not directly implement this interface. Please extend + * {@link AbstractObservableValueContractDelegate} instead. + *
+ * + * @since 1.1 + */ +public interface IObservableValueContractDelegate extends + IObservableContractDelegate { + + /** + * Creates a new observable value. + * + * @return observable value + */ + IObservableValue createObservableValue(); + + /** + * Returns the expected type of the observable. + * + * @param observable + * @return type + */ + Object getValueType(IObservableValue observable); +} Index: src/org/eclipse/jface/conformance/databinding/ObservableValueContractTests.java =================================================================== RCS file: src/org/eclipse/jface/conformance/databinding/ObservableValueContractTests.java diff -N src/org/eclipse/jface/conformance/databinding/ObservableValueContractTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/conformance/databinding/ObservableValueContractTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2007 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.conformance.databinding; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.IObservable; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.IValueChangeListener; +import org.eclipse.core.databinding.observable.value.ValueChangeEvent; + +/** + * @since 3.2 + */ +public class ObservableValueContractTests extends ObservableContractTests { + + private IObservableValueContractDelegate delegate; + + public ObservableValueContractTests( + IObservableValueContractDelegate delegate) { + super(delegate); + this.delegate = delegate; + } + + /** + * @param testName + * @param delegate + */ + public ObservableValueContractTests(String testName, + IObservableValueContractDelegate delegate) { + super(testName, delegate); + + this.delegate = delegate; + } + + public void testChangeNotifiesValueChangeListeners() throws Exception { + IObservableValue observable = delegate.createObservableValue(); + ValueChangeListener listener = new ValueChangeListener(observable) + .init(); + + delegate.change(observable); + assertEquals("On change value change listeners should be notified.", 1, + listener.count); + } + + public void testSettingSameValueDoesNotNotifiyValueChangeListeners() + throws Exception { + IObservableValue observable = delegate.createObservableValue(); + delegate.change(observable); + + ValueChangeListener listener = new ValueChangeListener(observable) + .init(); + Object value = observable.getValue(); + observable.setValue(value); + + assertEquals( + "When the current value is set on the observable a change does not occur thus value change listeners should not be notified.", + 0, listener.count); + } + + public void testSettingSameValueDoesNotNotifyChangeListeners() + throws Exception { + IObservableValue observable = delegate.createObservableValue(); + delegate.change(observable); + + ChangeListener listener = new ChangeListener(observable).init(); + Object value = observable.getValue(); + observable.setValue(value); + + assertEquals( + "When the current value is set on the observable a change does not occur thus change listeners should not be notified.", + 0, listener.count); + } + + public void testObservableTypeIsTheExpectedType() throws Exception { + IObservableValue observable = delegate.createObservableValue(); + assertEquals("Type of the value should be returned from getType().", + delegate.getValueType(observable), observable.getValueType()); + } + + public void testChangeListenersAreNotifiedBeforeValueChangeListeners() + throws Exception { + final List listeners = new ArrayList(); + IChangeListener changeListener = new IChangeListener() { + public void handleChange(ChangeEvent event) { + listeners.add(this); + } + }; + + IValueChangeListener valueChangeListener = new IValueChangeListener() { + public void handleValueChange(ValueChangeEvent event) { + listeners.add(this); + } + }; + + IObservableValue observable = delegate.createObservableValue(); + observable.addChangeListener(changeListener); + observable.addValueChangeListener(valueChangeListener); + + delegate.change(observable); + // not asserting the fact that both are notified as this is asserted in + // other tests + assertEquals( + "Change listeners should be notified before value change listeners.", + changeListener, listeners.get(0)); + assertEquals( + "Value change listeners should be notified after change listeners.", + valueChangeListener, listeners.get(1)); + } + + public void testValueChangeEventOldValueIsPreviousValue() throws Exception { + IObservableValue observable = delegate.createObservableValue(); + ValueChangeListener listener = new ValueChangeListener(observable) + .init(); + Object oldValue = observable.getValue(); + + delegate.change(observable); + + ValueChangeEvent event = listener.event; + assertEquals( + "When a value change event is fired the old value should be the previous value of the observable value.", + oldValue, event.diff.getOldValue()); + } + + public void testValueChangeEventObservableValue() throws Exception { + IObservableValue observable = delegate.createObservableValue(); + ValueChangeListener listener = new ValueChangeListener(observable) + .init(); + delegate.change(observable); + + ValueChangeEvent event = listener.event; + assertEquals( + "When a value change event is fired the new value should be the same as the current value of the observable value.", + observable.getValue(), event.diff.getNewValue()); + } + + public void testRemoveValueChangeListenerRemovesListener() throws Exception { + IObservableValue observable = delegate.createObservableValue(); + ValueChangeListener listener = new ValueChangeListener(observable) + .init(); + delegate.change(observable); + + // precondition + assertEquals("Value change listeners should be notified on change.", 1, + listener.count); + + observable.removeValueChangeListener(listener); + delegate.change(observable); + + assertEquals( + "Value change listeners should not be notified after they've been removed from the observable.", + 1, listener.count); + } + + /* package */static class ChangeListener implements IChangeListener { + int count; + + IObservable observable; + + ChangeListener(IObservable observable) { + this.observable = observable; + } + + ChangeListener init() { + observable.addChangeListener(this); + return this; + } + + public void handleChange(ChangeEvent event) { + count++; + } + } + + /* package */static class ValueChangeListener implements + IValueChangeListener { + int count; + + ValueChangeEvent event; + + private IObservableValue observable; + + ValueChangeListener(IObservableValue observable) { + this.observable = observable; + } + + ValueChangeListener init() { + observable.addValueChangeListener(this); + return this; + } + + public void handleValueChange(ValueChangeEvent event) { + count++; + this.event = event; + } + } +} Index: src/org/eclipse/jface/conformance/databinding/AbstractObservableContractDelegate.java =================================================================== RCS file: src/org/eclipse/jface/conformance/databinding/AbstractObservableContractDelegate.java diff -N src/org/eclipse/jface/conformance/databinding/AbstractObservableContractDelegate.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/conformance/databinding/AbstractObservableContractDelegate.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2007 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.conformance.databinding; + +import org.eclipse.core.databinding.observable.IObservable; + +/** + * Abstract implementation of {@link IObservableContractDelegate}. + * + * @since 1.1 + */ +public abstract class AbstractObservableContractDelegate implements + IObservableContractDelegate { + + public void setUp() { + // no op + } + + public void tearDown() { + // no op + } + + public void change(IObservable observable) { + // no op + } + + public void setStale(IObservable observable, boolean stale) { + // no op + } +} Index: src/org/eclipse/jface/conformance/databinding/IObservableContractDelegate.java =================================================================== RCS file: src/org/eclipse/jface/conformance/databinding/IObservableContractDelegate.java diff -N src/org/eclipse/jface/conformance/databinding/IObservableContractDelegate.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/conformance/databinding/IObservableContractDelegate.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2007 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.conformance.databinding; + +import org.eclipse.core.databinding.observable.IObservable; + +/** + * Delegate interface for observables. + * + *+ * Do not directly implement this interface. Please extend + * {@link AbstractObservableContractDelegate} instead. + *
+ * + * @since 1.1 + */ +public interface IObservableContractDelegate { + /** + * Notifies the delegate of the start of a test. + */ + void setUp(); + + /** + * Notifies the delegate of the end of a test. + */ + void tearDown(); + + /** + * Invokes an operation to set the stale state to the provided value. + * + * @param observable + * @param stale + */ + void setStale(IObservable observable, boolean stale); + + /** + * Creates a new observable. + * + * @return observable + */ + public IObservable createObservable(); + + /** + * Invokes a change operation on the observable resulting in a change event + * being fired from the observable. + * + * @param observable + */ + public void change(IObservable observable); +}