| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Matthew Hall - bugs 208858, 213145 |
| *******************************************************************************/ |
| |
| package org.eclipse.jface.databinding.conformance; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| |
| import junit.framework.Test; |
| |
| import org.eclipse.core.databinding.observable.ChangeEvent; |
| import org.eclipse.core.databinding.observable.IChangeListener; |
| import org.eclipse.core.databinding.observable.IObservableCollection; |
| import org.eclipse.jface.databinding.conformance.delegate.IObservableCollectionContractDelegate; |
| import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker; |
| import org.eclipse.jface.databinding.conformance.util.CurrentRealm; |
| import org.eclipse.jface.databinding.conformance.util.RealmTester; |
| import org.eclipse.jface.databinding.conformance.util.SuiteBuilder; |
| |
| /** |
| * Mutability tests for IObservableCollection. |
| * <p> |
| * This class is experimental and can change at any time. It is recommended to |
| * not subclass or assume the test names will not change. The only API that is |
| * guaranteed to not change are the constructors. The tests will remain public |
| * and not final in order to allow for consumers to turn off a test if needed by |
| * subclassing. |
| * </p> |
| * |
| * @since 3.2 |
| */ |
| public class MutableObservableCollectionContractTest extends ObservableDelegateTest { |
| private IObservableCollectionContractDelegate delegate; |
| |
| private IObservableCollection collection; |
| |
| public MutableObservableCollectionContractTest( |
| IObservableCollectionContractDelegate delegate) { |
| super(delegate); |
| this.delegate = delegate; |
| } |
| |
| public MutableObservableCollectionContractTest(String name, |
| IObservableCollectionContractDelegate delegate) { |
| super(name, delegate); |
| this.delegate = delegate; |
| } |
| |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| collection = (IObservableCollection) super.getObservable(); |
| } |
| |
| public void testAdd_ChangeEvent() throws Exception { |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.add(delegate.createElement(collection)); |
| } |
| }, "Collection.add(Object)", collection); |
| } |
| |
| public void testAdd_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.add(delegate.createElement(collection)); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testAdd_ChangeEventFiredAfterElementIsAdded() throws Exception { |
| final Object element = delegate.createElement(collection); |
| |
| assertContainsDuringChangeEvent(new Runnable() { |
| public void run() { |
| collection.add(element); |
| } |
| }, "Collection.add(Object)", collection, element); |
| } |
| |
| public void testAddAll_ChangeEvent() throws Exception { |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.addAll(Arrays.asList(new Object[] { delegate |
| .createElement(collection) })); |
| } |
| }, "Collection.addAll(Collection)", collection); |
| } |
| |
| public void testAddAll_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.addAll(Arrays.asList(new Object[] { delegate |
| .createElement(collection) })); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testAddAll_ChangeEventFiredAfterElementsAreAdded() |
| throws Exception { |
| final Object element = delegate.createElement(collection); |
| |
| assertContainsDuringChangeEvent(new Runnable() { |
| public void run() { |
| collection.addAll(Arrays.asList(new Object[] { element })); |
| } |
| }, "Collection.addAll(Collection)", collection, element); |
| } |
| |
| public void testRemove_ChangeEvent() throws Exception { |
| final Object element = delegate.createElement(collection); |
| collection.add(element); |
| |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.remove(element); |
| } |
| }, "Collection.remove(Object)", collection); |
| } |
| |
| public void testRemove_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.remove(delegate.createElement(collection)); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testRemove_ChangeEventFiredAfterElementIsRemoved() |
| throws Exception { |
| final Object element = delegate.createElement(collection); |
| collection.add(element); |
| |
| assertDoesNotContainDuringChangeEvent(new Runnable() { |
| public void run() { |
| collection.remove(element); |
| } |
| }, "Collection.remove(Object)", collection, element); |
| } |
| |
| public void testRemoveAll_ChangeEvent() throws Exception { |
| final Object element = delegate.createElement(collection); |
| collection.add(element); |
| |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.removeAll(Arrays.asList(new Object[] { element })); |
| } |
| }, "Collection.removeAll(Collection)", collection); |
| } |
| |
| public void testRemoveAll_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.removeAll(Arrays.asList(new Object[] { delegate.createElement(collection) })); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testRemoveAll_ChangeEventFiredAfterElementsAreRemoved() |
| throws Exception { |
| final Object element = delegate.createElement(collection); |
| collection.add(element); |
| |
| assertDoesNotContainDuringChangeEvent(new Runnable() { |
| public void run() { |
| collection.removeAll(Arrays.asList(new Object[] { element })); |
| } |
| }, "Collection.removeAll(Collection)", collection, element); |
| } |
| |
| public void testRemoveAll_NoChange() throws Exception { |
| ChangeEventTracker tracker = ChangeEventTracker.observe(collection); |
| collection.removeAll(Collections.EMPTY_LIST); |
| assertEquals( |
| "List.removeAll on an empty list should not fire a list change event", |
| 0, tracker.count); |
| } |
| |
| public void testRetainAll_ChangeEvent() throws Exception { |
| final Object element1 = delegate.createElement(collection); |
| collection.add(element1); |
| Object element2 = delegate.createElement(collection); |
| collection.add(element2); |
| |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.retainAll(Arrays.asList(new Object[] { element1 })); |
| } |
| |
| }, "Collection.retainAll(Collection)", collection); |
| } |
| |
| public void testRetainAll_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.retainAll(Collections.EMPTY_LIST); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testRetainAll_ChangeEventFiredAfterElementsAreRetained() |
| throws Exception { |
| Object element1 = delegate.createElement(collection); |
| collection.add(element1); |
| Object element2 = delegate.createElement(collection); |
| collection.add(element2); |
| |
| // precondition |
| assertTrue(collection.contains(element1)); |
| assertTrue(collection.contains(element2)); |
| |
| ContainsListener listener1 = new ContainsListener(collection, element1) |
| .init(); |
| ContainsListener listener2 = new ContainsListener(collection, element2) |
| .init(); |
| |
| // set contains the the opposite of the expected outcome to ensure they |
| // get set |
| listener1.contains = false; |
| listener2.contains = true; |
| |
| collection.retainAll(Arrays.asList(new Object[] { element1 })); |
| assertTrue( |
| formatFail("When Collection.retainAll(...) fires the change event the element should have been retained in the Collection."), |
| listener1.contains); |
| assertFalse( |
| formatFail("When Collection.retainAll(...) fires the change event the element should have been removed from the Collection."), |
| listener2.contains); |
| } |
| |
| public void testRetainAll_NoChangeFiresNoChangeEvent() throws Exception { |
| ChangeEventTracker tracker = ChangeEventTracker.observe(collection); |
| collection.retainAll(Collections.EMPTY_LIST); |
| assertEquals("List.retainAll should not have fired a change event:", |
| 0, tracker.count); |
| } |
| |
| public void testClear_ChangeEvent() throws Exception { |
| collection.add(delegate.createElement(collection)); |
| |
| assertChangeEventFired(new Runnable() { |
| public void run() { |
| collection.clear(); |
| } |
| }, "List.clear()", collection); |
| } |
| |
| public void testClear_RealmCheck() throws Exception { |
| RealmTester.exerciseCurrent(new Runnable() { |
| public void run() { |
| collection.clear(); |
| } |
| }, (CurrentRealm) collection.getRealm()); |
| } |
| |
| public void testClear_ChangeEventFiredAfterElementIsRemoved() |
| throws Exception { |
| Object element = delegate.createElement(collection); |
| collection.add(element); |
| |
| assertDoesNotContainDuringChangeEvent(new Runnable() { |
| public void run() { |
| collection.clear(); |
| } |
| }, "List.clear()", collection, element); |
| } |
| |
| /** |
| * Asserts that a ChangeEvent is fired once when the provided |
| * <code>runnable</code> is invoked and the source is the provided |
| * <code>collection</code>. |
| * |
| * @param runnable |
| * @param methodName |
| * @param collection |
| */ |
| /* package */void assertChangeEventFired(Runnable runnable, |
| String methodName, IObservableCollection collection) { |
| |
| ChangeEventTracker listener = ChangeEventTracker.observe(collection); |
| runnable.run(); |
| |
| assertEquals(formatFail(methodName + " should fire one ChangeEvent."), 1, |
| listener.count); |
| assertEquals( |
| formatFail(methodName |
| + "'s change event observable should be the created Collection."), |
| collection, listener.event.getObservable()); |
| } |
| |
| /** |
| * Asserts that when the change event is fired for the action contained in |
| * the <code>runnable</code> the change will have been applied to the |
| * <code>collection</code>. |
| * |
| * @param runnable |
| * @param methodName |
| * @param collection |
| * @param elementNotContained |
| */ |
| /* package */void assertDoesNotContainDuringChangeEvent(Runnable runnable, |
| String methodName, IObservableCollection collection, |
| Object elementNotContained) { |
| |
| // precondition |
| assertTrue(collection.contains(elementNotContained)); |
| |
| ContainsListener listener = new ContainsListener(collection, |
| elementNotContained).init(); |
| listener.contains = true; |
| collection.remove(elementNotContained); |
| assertFalse( |
| formatFail(new StringBuffer("When ") |
| .append(methodName) |
| .append( |
| " fires a change event the element should have been removed from the Collection.") |
| .toString()), listener.contains); |
| } |
| |
| /** |
| * Asserts that when the change event is fired for the action contained in |
| * the <code>runnable</code> the change will have been applied to the |
| * <code>collection</code>. |
| * |
| * @param runnable |
| * @param methodName |
| * @param collection |
| * @param elementContained |
| */ |
| /* package */void assertContainsDuringChangeEvent(Runnable runnable, |
| String methodName, IObservableCollection collection, |
| Object elementContained) { |
| ContainsListener listener = new ContainsListener(collection, |
| elementContained).init(); |
| |
| // precondition |
| assertFalse(collection.contains(elementContained)); |
| runnable.run(); |
| |
| assertTrue( |
| formatFail(new StringBuffer("When ") |
| .append(methodName) |
| .append( |
| " fires a change event the element should have been added to the Collection.") |
| .toString()), listener.contains); |
| } |
| |
| /* package */static class ContainsListener implements IChangeListener { |
| boolean contains; |
| |
| final private Object element; |
| |
| final private IObservableCollection collection; |
| |
| ContainsListener(IObservableCollection collection, Object element) { |
| this.element = element; |
| this.collection = collection; |
| } |
| |
| ContainsListener init() { |
| collection.addChangeListener(this); |
| return this; |
| } |
| |
| public void handleChange(ChangeEvent event) { |
| contains = collection.contains(element); |
| } |
| } |
| |
| public static Test suite(IObservableCollectionContractDelegate delegate) { |
| return new SuiteBuilder().addObservableContractTest( |
| MutableObservableCollectionContractTest.class, delegate) |
| .addObservableContractTest( |
| ObservableCollectionContractTest.class, delegate) |
| .build(); |
| } |
| } |