### 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); +}