package com.alexrnl.gameoflife.service;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;

import java.security.NoSuchAlgorithmException;
import java.util.List;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mock;

import com.alexrnl.gameoflife.world.World;

/**
 * Test suite for the {@link GameOfLifeController} class.
 * @author barfety_a
 */
public class GameOfLifeControllerTest {
	/** The controller to test */
	private GameOfLifeController	controller;
	/** The mocked listener */
	@Mock
	private WorldListener			listener;
	
	/**
	 * Set up test attributes.
	 * @throws NoSuchAlgorithmException
	 *         if the algorithm does not exists.
	 */
	@Before
	public void setUp () throws NoSuchAlgorithmException {
		initMocks(this);
		controller = new GameOfLifeController(new World(4, 4));
		controller.addWorldListener(listener);
	}
	
	/**
	 * Test method for {@link GameOfLifeController#addWorldListener(WorldListener)}.
	 */
	@Test
	public void testAddWorldListener () {
		final WorldListener secondListener = mock(WorldListener.class);
		controller.addWorldListener(secondListener);
		
		final List<WorldListener> listeners = controller.getWorldListeners();
		assertEquals(2, listeners.size());
		assertTrue(listeners.contains(listener));
		assertTrue(listeners.contains(secondListener));
	}
	
	/**
	 * Test that adding a <code>null</code> listener is not permitted.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testAddNullWorldListener () {
		controller.addWorldListener(null);
	}
	
	/**
	 * Test method for {@link GameOfLifeController#removeWorldListener(WorldListener)}.
	 */
	@Test
	public void testRemoveWorldListener () {
		controller.removeWorldListener(listener);
		assertTrue(controller.getWorldListeners().isEmpty());
	}
	
	/**
	 * Test that removing a <code>null</code> listener is not permitted.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testRemoveNullWorldListener () {
		controller.removeWorldListener(null);
	}
	
	/**
	 * Test method for {@link GameOfLifeController#getWorldListeners()}.
	 */
	@Test
	public void testGetWorldListeners () {
		final List<WorldListener> listeners = controller.getWorldListeners();
		assertEquals(1, listeners.size());
		assertEquals(listener, listeners.get(0));
	}
	
	/**
	 * Test method for {@link GameOfLifeController#grow()}.
	 */
	@Ignore @Test
	public void testGrow () {
		fail("Not yet implemented");
	}
	
	/**
	 * Test method for {@link GameOfLifeController#grow()}.
	 * Check that an exception in a listener does not disturb other listeners.
	 */
	@Test
	public void testGrowListenerException () {
		final WorldListener secondListener = mock(WorldListener.class);
		controller.addWorldListener(secondListener);
		doThrow(NullPointerException.class).when(listener).loopGeneration(any(World.class), eq(1));
		
		controller.grow();
		verify(secondListener).loopGeneration(any(World.class), eq(1));
	}
}

@@ -606,24 +606,73 @@
 to.Mock;%0D%0A%0D%0A
+import com.alexrnl.commons.error.TopLevelError;%0D%0A
 import com.a
@@ -3448,11 +3448,369 @@
 );%0D%0A%09%7D%0D%0A
+%09%0D%0A%09/**%0D%0A%09 * Test method for %7B@link GameOfLifeController#grow()%7D.%0D%0A%09 * Check that a clone exception is throwing a %7B@link TopLevelError%7D.%0D%0A%09 */%0D%0A%09@Test(expected = TopLevelError.class)%0D%0A%09public void testGrowWorldCloneException () %7B%0D%0A%09%09doThrow(CloneNotSupportedException.class).when(listener).loopGeneration(any(World.class), eq(1));%0D%0A%09%09controller.grow();%0D%0A%09%7D%0D%0A
 %7D%0D%0A

Add test for CloneNotSupportedException in controller's grow method