import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class Testing {
	
	private static int points = 0;
	
	@Test
	public void testAddAndIterator(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertTrue(l.add(1));
		//l.add("Hello");
		//l.add(3.141514);
	
		for (int i = 2; i < 100; i++) assertTrue(l.add(i));
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(i), it.next());
		}
		l = new DoublyLinkedList<>();
		for (int i = 0; i < 1000000; i++) l.add(i);
		points += 10;
	}
		
	@Test
	public void testAddLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		l.addLast(1);
		for (int i = 2; i < 100; i++) l.addLast(i);
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(i), it.next());
		}
		l = new DoublyLinkedList<>();
		for (int i = 0; i < 1000000; i++) l.addLast(i);
		points += 1;
	}
	
	@Test
	public void testOffer(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertTrue(l.offer(1));
		for (int i = 2; i < 100; i++) assertTrue(l.offer(i));
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(i), it.next());
		}
		l = new DoublyLinkedList<>();
		for (int i = 0; i < 1000000; i++) l.offer(i);
		points += 1;
	}
	
	@Test
	public void testOfferLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertTrue(l.offerLast(1));
		for (int i = 2; i < 100; i++) assertTrue(l.offerLast(i));
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(i), it.next());
		}
		l = new DoublyLinkedList<>();
		for (int i = 0; i < 1000000; i++) l.offerLast(i);
		points += 1;
	}
	
	@Test
	public void testAddFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		l.addFirst(1);
		for (int i = 2; i < 100; i++) l.addFirst(i);
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(100-i), it.next());
		}
		points += 1;
	}
	
	@Test
	public void testPush(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		l.push(1);
		for (int i = 2; i < 100; i++) l.push(i);
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(100-i), it.next());
		}
		points += 1;
	}
	
	@Test
	public void testOfferFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertTrue(l.offerFirst(1));
		for (int i = 2; i < 100; i++) assertTrue(l.offerFirst(i));
		Iterator<Integer> it = l.iterator();
		for (int i = 1; i < 100; i++) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(100-i), it.next());
		}
		points += 1;
	}
	
	@Test
	public void testSize(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(0, l.size());
		for (int i = 1; i < 100; i++) {
			l.add(i);
			assertEquals(i, l.size());
		}
		points += 5;
	}
	
	@Test
	public void testClear(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		l.add(1);
		assertEquals(1, l.size());
		l.clear();
		assertEquals(0, l.size());
		for (int i = 1; i < 50; i++) {
			l.add(i);
			assertEquals(i, l.size());
		}
		l.clear();
		assertEquals(0, l.size());
		for (int i = 50; i < 100; i++) {
			l.add(i);
			assertEquals(i-49, l.size());
		}
		l.clear();
		assertEquals(0, l.size());
		points += 2;
	}
	
	@Test
	public void testElement(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.element();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		for (int i = 1; i < 100; i++) {
			l.addFirst(i);
			assertEquals(new Integer(i), l.element());
		}
		assertEquals(99, l.size());
		l.clear();
		try {
			l.element();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 2;
	}
	
	@Test
	public void testGetFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.getFirst();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		for (int i = 1; i < 100; i++) {
			l.addFirst(i);
			assertEquals(new Integer(i), l.getFirst());
		}
		assertEquals(99, l.size());
		l.clear();
		try {
			l.getFirst();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 1;
	}
	
	@Test
	public void testPeek(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.peek());
		for (int i = 1; i < 100; i++) {
			l.addFirst(i);
			assertEquals(new Integer(i), l.peek());
		}
		assertEquals(99, l.size());
		l.clear();
		assertEquals(null, l.peek());
		points += 2;
	}
	
	@Test
	public void testPeekFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.peekFirst());
		for (int i = 1; i < 100; i++) {
			l.addFirst(i);
			assertEquals(new Integer(i), l.peekFirst());
		}
		assertEquals(99, l.size());
		l.clear();
		assertEquals(null, l.peekFirst());
		points += 1;
	}

	@Test
	public void testGetLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.getLast();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		for (int i = 1; i < 100; i++) {
			l.add(i);
			assertEquals(new Integer(i), l.getLast());
		}
		assertEquals(99, l.size());
		l.clear();
		try {
			l.getLast();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 2;
	}
	
	@Test
	public void testPeekLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.peekLast());
		for (int i = 1; i < 100; i++) {
			l.add(i); 
			assertEquals(new Integer(i), l.peekLast());
		}
		assertEquals(99, l.size());
		l.clear();
		assertEquals(null, l.peekLast());
		points += 2;
	}
	
	@Test
	public void testPoll(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.poll());
		l.add(42);
		assertEquals(new Integer(42), l.poll());
		assertEquals(0, l.size());
		assertEquals(null, l.poll());
		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 1; i < 100; i++) {
			assertEquals(new Integer(i), l.poll()); 
		}
		assertEquals(0, l.size());
		points += 5;
	}
	
	@Test
	public void testPollFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.pollFirst());
		l.add(42);
		assertEquals(new Integer(42), l.pollFirst());
		assertEquals(0, l.size());
		assertEquals(null, l.pollFirst());
		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 1; i < 100; i++) {
			assertEquals(new Integer(i), l.pollFirst()); 
		}
		assertEquals(0, l.size());
		points += 1;
	}

	@Test
	public void testRemove(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.remove();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		l.add(42);
		assertEquals(new Integer(42), l.remove());
		assertEquals(0, l.size());
		try {
			l.remove();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 1; i < 100; i++) {
			assertEquals(new Integer(i), l.remove()); 
		}
		assertEquals(0, l.size());
		try {
			l.remove();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 2;
	}
	
	@Test
	public void testPop(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.pop();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		l.add(42);
		assertEquals(new Integer(42), l.pop());
		assertEquals(0, l.size());
		try {
			l.pop();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 1; i < 100; i++) {
			assertEquals(new Integer(i), l.pop()); 
		}
		assertEquals(0, l.size());
		try {
			l.pop();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 1;
	}
	
	@Test
	public void testRemoveFirst(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.removeFirst();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		l.add(42);
		assertEquals(new Integer(42), l.removeFirst());
		assertEquals(0, l.size());
		try {
			l.removeFirst();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 1; i < 100; i++) {
			assertEquals(new Integer(i), l.removeFirst()); 
		}
		assertEquals(0, l.size());
		try {
			l.removeFirst();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 1;
	}
	
	@Test
	public void testPollLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(null, l.pollLast());
		l.add(42);
		assertEquals(new Integer(42), l.pollLast());
		assertEquals(0, l.size());
		assertEquals(null, l.pollLast());
		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 99; i >= 1; i--) {
			assertEquals(new Integer(i), l.pollLast()); 
		}
		assertEquals(0, l.size());
		assertEquals(null, l.pollLast());
		points += 5;
	}
	
	@Test
	public void testRemoveLast(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.removeLast();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		l.add(42);
		assertEquals(new Integer(42), l.removeLast());
		assertEquals(0, l.size());
		try {
			l.removeLast();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		
		for (int i = 1; i < 100; i++) {
			l.add(i); 
		}
		assertEquals(99, l.size());
		for (int i = 99; i >= 1; i--) {
			assertEquals(new Integer(i), l.removeLast()); 
		}
		assertEquals(0, l.size());
		try {
			l.removeLast();
			fail("Did not throw NoSuchElementException");
		} catch (Exception e){
			if (!(e instanceof NoSuchElementException)) {
				fail("Did not throw NoSuchElementException");				
			}
		}
		points += 2;
	}
	
	// >>>>>>>>>>>>>>>
	
	@Test
	public void testDescendingIterator(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertTrue(l.add(1));
		for (int i = 2; i < 100; i++) assertTrue(l.add(i));
		Iterator<Integer> it = l.descendingIterator();
		for (int i = 99; i >= 1; i--) {
			assertTrue(it.hasNext());
			assertEquals(new Integer(i), it.next());
		}
		points += 4;
	}
	
	@Test
	public void testContains(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertFalse(l.contains(42));
		l.add(1);
		assertFalse(l.contains(42));
		for (int i = 2; i < 100; i++) l.add(i);
		assertTrue(l.contains(42));
		assertFalse(l.contains(101));
		points += 2;
	}
	
	@Test
	public void testIndexOf(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(-1, l.indexOf(42));
		l.add(1);
		assertEquals(-1, l.indexOf(42));
		for (int i = 2; i < 100; i++) l.add(i);
		for (int i = 2; i < 100; i++) l.add(i);
		assertEquals(2, l.indexOf(3));
		assertEquals(-1, l.indexOf(101));
		points += 3;
	}
	
	@Test
	public void testLastIndexOf(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals(-1, l.lastIndexOf(42));
		l.add(1);
		assertEquals(-1, l.lastIndexOf(42));
		for (int i = 2; i < 100; i++) l.add(i);
		assertEquals(2, l.lastIndexOf(3));
		for (int i = 2; i < 100; i++) l.add(i);
		assertEquals(100, l.lastIndexOf(3));
		assertEquals(-1, l.lastIndexOf(101));
		points += 3;
	}
	
	@Test
	public void testGet(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.get(0);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		l.add(1);
		try {
			l.get(-1);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		try {
			l.get(1);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		for (int i = 2; i < 100; i++) l.add(i);
		assertEquals(new Integer(3), l.get(2)); 
		assertEquals(new Integer(99), l.get(98));
		points += 5;
	}
	
	@Test
	public void testToArray(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		for (int i = 2; i < 100; i++) l.add(i);
		Object a[] = l.toArray();
		assertEquals(98, a.length);
		for (int i = 0; i < 98; i++) {
			assertEquals(i+2, a[i]);
		}
		points += 3;
	}
	
	@Test
	public void testToString(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertEquals("[]", l.toString());
		String s = "[";
		for (int i = 2; i < 100; i++) {
			l.add(i);
			s+= i + ", ";
		}
		l.add(100);
		s+= 100 + "]";
		assertEquals(s, l.toString());
		points += 3;
	}
	
	@Test
	public void testRemoveObject(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertFalse(l.remove(new Integer(42)));
		l.add(1);
		assertFalse(l.remove(new Integer(42)));
		assertTrue(l.remove(new Integer(1)));
		assertFalse(l.remove(new Integer(1)));
		assertEquals(0, l.size());
		
		for (int i = 1; i < 50; i++) l.add(i);
		for (int i = 51; i < 100; i++) l.add(i);
		assertFalse(l.remove(new Integer(50)));
		assertTrue(l.remove(new Integer(1)));
		assertFalse(l.remove(new Integer(1)));
		assertTrue(l.remove(new Integer(2)));
		
		assertTrue(l.remove(new Integer(99)));
		assertFalse(l.remove(new Integer(99)));
		assertTrue(l.remove(new Integer(98)));
		
		Iterator<Integer> it = l.descendingIterator();
		for (int k = 97; k > 50; k--) {
			assertEquals(new Integer(k), it.next());
		}
		for (int k = 49; k > 2; k--) {
			assertEquals(new Integer(k), it.next());
		}
		
		it = l.iterator();
		for (int k = 3; k < 50; k++) {
			assertEquals(new Integer(k), it.next());
		}
		for (int k = 51; k < 98; k++) {
			assertEquals(new Integer(k), it.next());
		}

		
		points += 15;
	}
	
	@Test
	public void testRemoveFirstOccurence(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertFalse(l.removeFirstOccurrence(new Integer(42)));
		l.add(new Integer(1));
		assertFalse(l.removeFirstOccurrence(new Integer(42)));
		assertTrue(l.removeFirstOccurrence(new Integer(1)));
		assertFalse(l.removeFirstOccurrence(new Integer(1)));
		assertEquals(0, l.size());
		
		for (int i = 1; i < 50; i++) l.add(i);
		for (int i = 51; i < 100; i++) l.add(i);
		assertFalse(l.removeFirstOccurrence(new Integer(50)));
		assertTrue(l.removeFirstOccurrence(new Integer(1)));
		assertFalse(l.removeFirstOccurrence(new Integer(1)));
		assertTrue(l.removeFirstOccurrence(new Integer(2)));
		
		assertTrue(l.removeFirstOccurrence(new Integer(99)));
		assertFalse(l.removeFirstOccurrence(new Integer(99)));
		assertTrue(l.removeFirstOccurrence(new Integer(98)));
		points += 1;
	}
	
	@Test
	public void testRemoveLastOccurence(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		assertFalse(l.removeLastOccurrence(new Integer(42)));
		l.add(1);
		assertFalse(l.removeLastOccurrence(new Integer(42)));
		assertTrue(l.removeLastOccurrence(new Integer(1)));
		assertFalse(l.removeLastOccurrence(new Integer(1)));
		assertEquals(0, l.size());
		
		for (int i = 1; i < 50; i++) l.add(i);
		for (int i = 1; i < 50; i++) l.add(i);
		assertEquals(new Integer(12), l.get(60));
		assertTrue(l.removeLastOccurrence(new Integer(12)));
		assertEquals(new Integer(13), l.get(60));
		assertTrue(l.removeLastOccurrence(new Integer(12)));
		assertFalse(l.removeLastOccurrence(new Integer(12)));

		assertTrue(l.removeLastOccurrence(new Integer(1)));
		assertTrue(l.removeLastOccurrence(new Integer(1)));
		assertFalse(l.removeLastOccurrence(new Integer(1)));
		assertTrue(l.removeLastOccurrence(new Integer(2)));
		
		assertTrue(l.removeLastOccurrence(new Integer(49)));
		assertTrue(l.removeLastOccurrence(new Integer(49)));
		assertFalse(l.removeLastOccurrence(new Integer(49)));
		assertTrue(l.removeLastOccurrence(new Integer(48)));
		points += 1;
	}

	@Test
	public void testRemoveIndex(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.remove(0);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		l.add(1);
		try {
			l.remove(-1);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		try {
			l.remove(1);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		assertEquals(new Integer(1), l.remove(0));
		assertEquals(0, l.size());
		try {
			l.remove(0);
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		
		for (int i = 1; i < 100; i++) l.add(i);
		assertEquals(new Integer(51), l.remove(50));
		for (int i = 1; i < 50; i++) assertEquals(new Integer(i), l.remove(0));
		assertEquals(49, l.size());
		for (int i = 48; i >= 2; i--) assertEquals(new Integer(i+51), l.remove(i));
		assertEquals(2, l.size());
		points += 5;
	}
	
	@Test
	public void testAddIndex(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		try {
			l.add(-1, new Integer(42));
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		try {
			l.add(1, new Integer(42));
			fail("Did not throw IndexOutOfBoundsException");
		} catch (Exception e){
			if (!(e instanceof IndexOutOfBoundsException)) {
				fail("Did not throw IndexOutOfBoundsException");				
			}
		}
		l.add(0, new Integer(42));
		assertEquals("[42]", l.toString());
		assertEquals(1, l.size());
		for (int i = 1; i < 5; i++) l.add(0, new Integer(i));
		assertEquals("[4, 3, 2, 1, 42]", l.toString());
		assertEquals(5, l.size());
		for (int i = 1; i < 5; i++) l.add(i+4, new Integer(i));
		assertEquals("[4, 3, 2, 1, 42, 1, 2, 3, 4]", l.toString());
		assertEquals(9, l.size());
		l.add(1, new Integer(99));
		assertEquals("[4, 99, 3, 2, 1, 42, 1, 2, 3, 4]", l.toString());
		assertEquals(10, l.size());
		l.add(9, new Integer(99));
		assertEquals("[4, 99, 3, 2, 1, 42, 1, 2, 3, 99, 4]", l.toString());
		assertEquals(11, l.size());
		points += 5;
	}
	
	@Test
	public void testRemoveInIterator(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		Iterator<Integer> i = l.iterator();
		assertFalse(i.hasNext());
		l.add(42);
		i = l.iterator();
		assertTrue(i.hasNext());
		try {
			 i.remove();
			 fail("Did not throw IllegalStateException");
			} catch (Exception e){
			if (!(e instanceof IllegalStateException)) {
				fail("Did not throw IllegalStateException");				
				}
			}
		assertTrue(i.hasNext());
		i.next();
		i.remove();
		assertEquals(0, l.size());
		
		l = new DoublyLinkedList<>();
		l.add(42);
		l.add(88);;
		i = l.iterator();
		assertEquals(new Integer(42), i.next());
		i.remove();
		assertEquals(new Integer(88), i.next());	
		assertFalse(i.hasNext());
		assertEquals(1, l.size());
		
		l = new DoublyLinkedList<>();
		l.add(42);
		l.add(88);;
		i = l.iterator();
		assertEquals(new Integer(42), i.next());
		assertEquals(new Integer(88), i.next());	
		i.remove();
		assertFalse(i.hasNext());
		assertEquals(1, l.size());	
		points += 5;
	}
	
	@Test
	public void testClone(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(i);
		}
		DoublyLinkedList<Integer> ll = (DoublyLinkedList<Integer>) l.clone();
		assertEquals(l.size(), ll.size());
		assertEquals(l.toString(), ll.toString());
		l.remove(1);
		assertNotEquals(l.toString(), ll.toString());
		ll.remove(1);
		assertEquals(l.toString(), ll.toString());
		points += 3;
	}
	
	@Test
	public void testRemoveInIncreasingIterator(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		Iterator<Integer> it = l.iterator();
		try {
		 it.remove();
		 fail("Did not throw IllegalStateException");
		} catch (Exception e){
		if (!(e instanceof IllegalStateException)) {
			fail("Did not throw IllegalStateException");				
			}
		}
		if (it.hasNext()) it.next();
		it.remove();
		assertEquals("[2, 3, 4, 5, 6, 7, 8, 9]", l.toString());
		try {
			 it.remove();
			 fail("Did not throw IllegalStateException");
		} catch (Exception e){
		if (!(e instanceof IllegalStateException)) {
				fail("Did not throw IllegalStateException");				
			}
		}
		l.add(new Integer(42));
		try {
			 it.next();
			 fail("Did not throw ConcurrentModificationException");
		} catch (Exception e){
		if (!(e instanceof ConcurrentModificationException)) {
				fail("Did not throw ConcurrentModificationException");				
			}
		}
		
		l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		it = l.iterator();
		if (it.hasNext()) it.next();
		l.add(new Integer(42));
		try {
			 it.remove();
			 fail("Did not throw ConcurrentModificationException");
		} catch (Exception e){
		if (!(e instanceof ConcurrentModificationException)) {
				fail("Did not throw ConcurrentModificationException");				
			}
		}
		
		l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		it = l.iterator();
		
		for (int i = 1; i < 10; i++) it.next();
		it.remove();
		assertEquals("[1, 2, 3, 4, 5, 6, 7, 8]", l.toString());

		points += 4;
	}
	
	@Test
	public void testRemoveInDecreasingIterator(){
		DoublyLinkedList<Integer> l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		Iterator<Integer> it = l.descendingIterator();
		try {
		 it.remove();
		 fail("Did not throw IllegalStateException");
		} catch (Exception e){
		if (!(e instanceof IllegalStateException)) {
			fail("Did not throw IllegalStateException");				
			}
		}
		if (it.hasNext()) it.next();
		it.remove();
		assertEquals("[1, 2, 3, 4, 5, 6, 7, 8]", l.toString());
		try {
			 it.remove();
			 fail("Did not throw IllegalStateException");
		} catch (Exception e){
		if (!(e instanceof IllegalStateException)) {
				fail("Did not throw IllegalStateException");				
			}
		}
		l.add(new Integer(42));
		try {
			 it.next();
			 fail("Did not throw ConcurrentModificationException");
		} catch (Exception e){
		if (!(e instanceof ConcurrentModificationException)) {
				fail("Did not throw ConcurrentModificationException");				
			}
		}
		
		l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		it = l.descendingIterator();
		if (it.hasNext()) it.next();
		l.add(new Integer(42));
		try {
			 it.remove();
			 fail("Did not throw ConcurrentModificationException");
		} catch (Exception e){
		if (!(e instanceof ConcurrentModificationException)) {
				fail("Did not throw ConcurrentModificationException");				
			}
		}
		
		l = new DoublyLinkedList<>();
		for (int i = 1; i < 10; i++) {
			l.add(new Integer(i));
		}
		it = l.descendingIterator();
		
		for (int i = 1; i < 10; i++) it.next();
		it.remove();
		assertEquals("[2, 3, 4, 5, 6, 7, 8, 9]", l.toString());
		points += 3;
	}

	@AfterClass
	public static void testDoNothing(){
		System.out.println("Points: " + points);
	}	
	
}