blob: ba34da54fb9a1d8c6214d95db19a25549f371ee0 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}