/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nomad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Created on Sep 3, 2006
*/
package test.java.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.NoSuchElementException;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import test.java.lang.ObjectTest;
/**
* Tests {@link java.util.Collection}
* @author Christian Schneider
*/
public abstract class CollectionTest<E> extends ObjectTest
{
/**
* Returns an empty instance of the tested collection.
* Two calls must return two objects <code>a</code> and <code>b</code>
* where <code>a!=b</code> is true.
*
* @return empty instance of the tested collection
*/
public abstract Collection<E> createEmptyCollection();
/**
* Creates an element that is not in the specified collection.
* These elements are added to the collection.
*
* @param c the collection
* @return a unique element
* @throws NoSuchElementException limit of elements that can be added to the collection is reached
*/
public abstract E createUniqueElement(Collection<E> c)
throws NoSuchElementException;
/**
* Returns the maximum number of elements that can be created and added
* to a collection for testing purposes. Returns <code>0</code>
* when the number of elements is not limited.
*/
public abstract int getElementLimit();
/**
* Returns the maximum number of elements that are created
* and added to a single list. The return value is in the range
* [2..10].
*/
public int getLimit()
{
int l = getElementLimit();
return (l==0) ? 10 : Math.max(2, Math.min(10, l));
}
/**
* returns an instance of the tested collection that contains different elements
*
* @return
* @see #createEmptyCollection()
* @see #createUniqueElement(Collection)
* @see #getLimit()
*/
public Collection<E> createCollection()
{
Collection<E> c = createEmptyCollection();
for (int i=getLimit()-1;i>=0;i--)
c.add(createUniqueElement(c));
return c;
}
/**
* returns a collection of objects that were not created before
* and that are all different and for two elements a and b a.equals(b) is false
*
* @return
* @see #createEmptyCollection()
* @see #createUniqueElement(Collection)
* @see #getLimit()
*/
public Collection<Object> createUniqueCollection()
{
int size = getLimit();
ArrayList<Object> list = new ArrayList<Object>(size);
for (int i=getLimit()-1;i>=0;i--)
list.add(new Object());
return list;
}
/**
* Tests {@link #createUniqueCollection()}
*/
@Test
public void createUniqueCollectionTest()
{
Collection<?> c = createUniqueCollection();
Assert.assertTrue(c.size()>0);
Object[] items = c.toArray();
for (int i=0;i<items.length-1;i++)
{
Object a = items[i];
for (int j=i+1;j<items.length;j++)
{
Object b = items[j];
Assert.assertTrue(a!=b);
Assert.assertTrue(!a.equals(b));
}
}
}
/**
* Returns true when the collection supports adding equal elements twice
*/
public abstract boolean supportsMultipleAdds();
/**
* Tests whether {@link #createCollection()} contains
* at least two elements.
*/
@Test
public void testCreateCollection()
{
Assert.assertTrue(createCollection().size()>=2);
}
/**
* Tests whether {@link #createEmptyCollection()} creates an
* empty collection.
*/
@Test
public void testCreateEmptyCollection()
{
Collection<E> c = createEmptyCollection();
Assert.assertTrue(c.size()==0);
}
/**
* Tests whether {@link #getElementLimit()} returns a value
* >=0
*/
@Test
public void testGetElementLimit()
{
Assert.assertTrue(getElementLimit()>=0);
}
/**
* Tests {@link #createUniqueElement(Collection)}.
*/
@Test
public void testCreateUniqueElement()
{
Collection<E> c = createEmptyCollection();
for (int i=0;i<getLimit();i++)
{
E element = createUniqueElement(c);
Assert.assertTrue(element!=null);
Assert.assertTrue(!c.contains(element));
c.add(element);
}
}
/**
* Tests {@link Collection#size()} and {@link Collection#isEmpty()}
*/
@Test
public void testSizeAndIsEmpty()
{
Collection<E> c = createEmptyCollection();
int expectedSize = 0;
for (;expectedSize<getLimit();expectedSize++)
{
Assert.assertTrue(expectedSize==c.size());
Assert.assertTrue(c.isEmpty()==(expectedSize==0));
c.add(createUniqueElement(c));
}
Assert.assertTrue(expectedSize==c.size());
Assert.assertTrue(c.isEmpty()==(expectedSize==0));
while (c.size()>0)
{
E element = c.iterator().next();
c.remove(element);
expectedSize --;
Assert.assertTrue(expectedSize==c.size());
Assert.assertTrue(c.isEmpty()==(expectedSize==0));
}
}
/**
* When {@link #supportsMultipleAdds()} is true, tests
* whether two elements a, b where a.equals(b)==true
* can be added, otherwise tests if adding a and b fails.
*
* Note: this test is not necessary when the {@link Object#equals(java.lang.Object)} method
* is implemented correctly.
*/
@Test
public void equalElementTest()
{
if (supportsMultipleAdds())
{
Collection<E> c = createEmptyCollection();
E e = createUniqueElement(c);
Assert.assertTrue(c.add(e));
Assert.assertTrue("adding twice the same element should be possible",
c.add(e));
Assert.assertTrue(c.size()==2);
}
else
{
Collection<E> c = createEmptyCollection();
E e = createUniqueElement(c);
Assert.assertTrue(c.add(e));
Assert.assertTrue("adding twice the same element should not be possible",
!c.add(e));
Assert.assertTrue(c.size()==1);
}
}
/**
* Creates one empty collection and one with multiple elements added.
*/
@Override
public Object[] createEqualsTestInstances()
{
return new Object[] {
createEmptyCollection(),
createCollection()
};
}
/**
* Tests {@link Collection#contains(java.lang.Object)}
* TODO test exceptions
*/
@Test
public void testContains()
{
Collection<E> c = createCollection();
c.remove(c.iterator().next()); // remove one element see getLimit()
E unique = createUniqueElement(c);
Assert.assertTrue (!c.contains(unique));
for (E e : c)
Assert.assertTrue(c.contains(e));
}
/**
* Tests {@link Collection#containsAll(java.util.Collection)}
* TODO test exceptions
*/
@Test
public void testContainsAll()
{
Collection<E> c = createCollection();
Assert.assertTrue (c.containsAll(c));
Assert.assertTrue (c.containsAll(createEmptyCollection()));
E unique = c.iterator().next();
Assert.assertTrue(c.remove(unique)); // remove one element see getLimit()
Collection<E> c2 = createEmptyCollection();
c2.add(unique);
Assert.assertTrue(!c.containsAll(c2));
// TODO requires c initially contains at least 2 elements
c2.add(c.iterator().next());
Assert.assertTrue(!c.containsAll(c2));
}
/**
* Tests {@link Collection#toArray()}
*/
@Test
public void testToArray()
{
Assert.assertTrue(createEmptyCollection().toArray().length==0);
Collection<E> c = createCollection();
Object[] array = c.toArray();
Assert.assertTrue(c.size()==array.length);
for (Object e : array)
{
Assert.assertTrue(c.contains(e));
}
}
/**
* Tests {@link Collection#toArray(T[])}
* TODO implement test
*/
@Ignore("test not implemented: Collection.toArray(T[])")
@Test
public void testToArray2()
{
throw new UnsupportedOperationException();
}
/**
* Tests {@link Collection#add(E)}
* TODO implement test
*/
@Ignore("test not implemented: Collection.add(E)")
@Test
public void testAdd()
{
throw new UnsupportedOperationException();
}
/**
* Tests {@link Collection#remove(java.lang.Object)}
* TODO implement test
*/
@Ignore("test not implemented: Collection.remove(java.lang.Object)")
@Test
public void testRemove()
{
throw new UnsupportedOperationException();
}
/**
* Tests {@link Collection#addAll(java.util.Collection)}
* TODO implement test
*/
@Ignore("test not implemented: Collection.addAll(java.util.Collection)")
@Test
public void testAddAll()
{
throw new UnsupportedOperationException();
}
/**
* Tests {@link Collection#removeAll(java.util.Collection)}
* TODO test exceptions
*/
@Test
public void testRemoveAll()
{
Collection<E> c = createCollection();
Collection<E> copy = new ArrayList<E>();
for (E e : c)
copy.add(e);
Assert.assertTrue (c.removeAll(copy));
Assert.assertTrue (c.size()==0);
c = createCollection();
copy.clear();
for (E e : c)
copy.add(e);
// remove one element
copy.remove(copy.iterator().next());
Assert.assertTrue (c.removeAll(copy));
Assert.assertTrue (c.size()==1); // one element left
Assert.assertTrue(!c.removeAll(createUniqueCollection()));
}
/**
* Tests {@link Collection#retainAll(java.util.Collection)}
* TODO test exceptions
*/
@Test
public void testRetainAll()
{
Collection<E> c = createCollection();
int sizeBefore = c.size();
c.retainAll(c);
Assert.assertTrue(c.size()==sizeBefore);
c.retainAll(createEmptyCollection());
Assert.assertTrue(c.size()==0);
}
/**
* Tests {@link Collection#clear()}
*/
@Test
public void testClear()
{
Collection<E> c;
c = createEmptyCollection();
c.clear();
Assert.assertTrue(c.isEmpty());
c = createCollection();
c.clear();
Assert.assertTrue(c.isEmpty());
}
}