package uk.co.webamoeba.mockito.collections.inject;

import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ArrayBlockingQueue;

import org.junit.Test;

import uk.co.webamoeba.mockito.collections.exception.MockitoCollectionsException;

/**
 * @author James Kennard
 */
@SuppressWarnings("unchecked")
public class CollectionFactoryTest {

	private CollectionFactory factory = new CollectionFactory();

	@Test
	public void shouldCreateCollectionGivenCollection() {
		shouldCreateCollection(Collection.class);
	}

	@Test
	public void shouldCreateCollectionGivenCollectionAndContents() {
		shouldCreateCollectionGivenContents(Collection.class);
	}

	@Test
	public void shouldCreateCollectionGivenSortedSet() {
		shouldCreateCollection(SortedSet.class);
	}

	@Test
	public void shouldCreateCollectionGivenSortedSetAndContents() {
		shouldCreateCollection(SortedSet.class, Arrays.<Object> asList("ABC", "DEF", "GHI"));
	}

	@Test
	public void shouldCreateCollectionGivenSet() {
		shouldCreateCollection(Set.class);
	}

	@Test
	public void shouldCreateCollectionGivenSetAndContents() {
		shouldCreateCollectionGivenContents(Set.class);
	}

	@Test
	public void shouldCreateCollectionGivenList() {
		shouldCreateCollection(List.class);
	}

	@Test
	public void shouldCreateCollectionGivenListAndContents() {
		shouldCreateCollectionGivenContents(List.class);
	}

	@Test
	public void shouldCreateCollectionGivenQueue() {
		shouldCreateCollection(Queue.class);
	}

	@Test
	public void shouldCreateCollectionGivenQueueAndContents() {
		shouldCreateCollectionGivenContents(Queue.class);
	}

	@Test
	public void shouldCreateCollectionGivenSpecificType() {
		shouldCreateCollection(LinkedList.class);
	}

	@Test
	public void shouldCreateCollectionGivenSpecificTypeAndContents() {
		shouldCreateCollectionGivenContents(LinkedList.class);
	}

	@Test(expected = MockitoCollectionsException.class)
	public void shouldFailToCreateCollectionGivenCannotInstantiateSpecificType() {
		shouldCreateCollection(ArrayBlockingQueue.class);
	}

	@Test(expected = MockitoCollectionsException.class)
	public void shouldFailToCreateCollectionGivenCannotInstantiateSpecificTypeAndContents() {
		shouldCreateCollectionGivenContents(ArrayBlockingQueue.class);
	}

	private <T extends Collection<Object>> void shouldCreateCollection(Class<T> clazz) {
		shouldCreateCollection(clazz, null);
	}

	private <T extends Collection<Object>> void shouldCreateCollectionGivenContents(Class<T> clazz) {
		Collection<Object> contents = Arrays.<Object> asList("Some Contents", 'A', 12L, 3.0f);
		shouldCreateCollection(clazz, contents);
	}

	private <T extends Collection<Object>> void shouldCreateCollection(Class<T> clazz, Collection<Object> contents) {
		// Given
		Class<T> collectionClass = clazz;

		// When
		Collection<?> collection = factory.createCollection(collectionClass, contents);

		// Then
		assertTrue(collectionClass.isAssignableFrom(collection.getClass()));
		if (contents != null) {
			assertTrue(collection.containsAll(contents));
		}
	}
}

@@ -42,24 +42,69 @@
 ns.inject;%0A%0A
+import static org.junit.Assert.assertEquals;%0A
 import stati
@@ -189,16 +189,43 @@
 ection;%0A
+import java.util.Iterator;%0A
 import j
@@ -2719,26 +2719,20 @@
 zz) %7B%0A%09%09
-Collection
+List
 %3CObject%3E
@@ -2931,26 +2931,20 @@
  clazz, 
-Collection
+List
 %3CObject%3E
@@ -3031,9 +3031,14 @@
 ion%3C
-?
+Object
 %3E co
@@ -3222,44 +3222,254 @@
 sert
-True(collection.containsAll(contents
+Equals(contents.size(), collection.size());%0A%09%09%09Iterator%3CObject%3E iterator = collection.iterator();%0A%09%09%09for (int i = 0; i %3C contents.size(); i++) %7B%0A%09%09%09%09assertEquals(contents.get(i), iterator.next());%0A%09%09%09%7D%0A%09%09%7D else %7B%0A%09%09%09assertTrue(collection.isEmpty(
 ));%0A

Test ordering of elements from CollectionFactory