package eu.dnetlib.enabling.resultset;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

/**
 * tests the IterableResult class
 * 
 * @author claudio
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class IterableResultSetTest {

	/**
	 * number of total elements 
	 */
	private static int NUM_ELEM = 100;
	
	/**
	 * number of elements available to fetch
	 */
	private static int FETCH_SIZE = 10;
	
	@Mock
	private ResultSet mockResultSet;
	
	/**
	 * a list used to compare elements.
	 */
	private List<String> list;
	
	/**
	 * Iterator associated with the test list.
	 */
	private Iterator<String> iter;
	
	/**
	 * Object to test.
	 */
	private IterableResultSet iterResultSet;

	@Before
	public void setUp() {
		list = new ArrayList<String>();
		for (int i=0; i< NUM_ELEM; i++)
			list.add("XXXXX " + i);
				
		iter = list.iterator();
		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
		
		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
		iterResultSet.setResultSet(mockResultSet);
	}
	
	@Test
	public void testIterableResultSet() {
		assertNotNull(iterResultSet);
		assertTrue(iterResultSet.getSize() > 0);
	}

	@Test(expected=RuntimeException.class)
	public void testGetResult_fail_1() {
		iterResultSet.getResult(0, 5);
	}

	@Test(expected=RuntimeException.class)
	public void testGetResult_fail_2() {
		iterResultSet.getResult(1, 5);
		iterResultSet.getResult(1, 5);
	}
	
	@Test(expected=RuntimeException.class)
	public void testGetResult_fail_3() {
		iterResultSet.getResult(1, 5);
		iterResultSet.getResult(6, 5);
	}
	
	@Test(expected=RuntimeException.class)
	public void testGetResult_fail_4() {
		iterResultSet.getResult(1, 5);
		iterResultSet.getResult(7, 10);
	}
	
	@Test
	public void testGetResult_success_1() {
		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
		for (int i=0; i<NUM_ELEM; i++) {
			assertEquals(list.get(i), result.get(i));
		}
	}
	
	@Test
	public void testGetResult_success_2() {
		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
		
		for (int i=0; i<NUM_ELEM; i++) {
			assertEquals(list.get(i), result.get(i));
			iter.next();
		}
		verify(mockResultSet).close();
	}

	@Test
	public void testGetResult_success_3() {
		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
			iterResultSet.getResult(i, i + FETCH_SIZE-1);
		verify(mockResultSet, times(1)).close();
	}
	
	@Test
	public void testGetResult_success_4() {
		iterResultSet.getResult(1, NUM_ELEM + 1);
		verify(mockResultSet, times(1)).close();
	}
	
	@Test
	public void testGetResultSet_success_1() {
		assertNotNull(iterResultSet.getResultSet());
	}

	@Test
	public void testGetSize_fail_1() {
		iterResultSet.getResult(1, 8);
		assertNotSame(7, iterResultSet.getSize());
		assertNotSame(9, iterResultSet.getSize());
	}
	
	@Test
	public void testGetSize_success_1() {
		iterResultSet.getResult(1, 8);
		assertEquals(FETCH_SIZE, iterResultSet.getSize());
	}

}
