/*
Copyright (c) 2012 LinkedIn Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* $Id: $
*/
package com.linkedin.r2.util;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Random;
/**
* @author Steven Ihde
* @version $Revision: $
*/
public class TestLinkedDeque
{
@Test
public void testAdd()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(99);
q.add(99);
Assert.assertEquals(q, control);
}
@Test
public void testAddLast()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(99);
q.addLast(99);
Assert.assertEquals(q, control);
}
@Test
public void testAddFirst()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(0, 99);
q.addFirst(99);
Assert.assertEquals(q, control);
}
@Test
public void testOffer()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(99);
Assert.assertTrue(q.offer(99));
Assert.assertEquals(q, control);
}
@Test
public void testOfferLast()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(99);
Assert.assertTrue(q.offerLast(99));
Assert.assertEquals(q, control);
}
@Test
public void testOfferFirst()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
control.add(0, 99);
Assert.assertTrue(q.offerFirst(99));
Assert.assertEquals(q, control);
}
@Test
public void testRemove()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.remove(), control.remove(0));
Assert.assertEquals(q, control);
}
@Test
public void testRemoveFirst()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.removeFirst(), control.remove(0));
Assert.assertEquals(q, control);
}
@Test
public void testRemoveLast()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.removeLast(), control.remove(control.size() - 1));
Assert.assertEquals(q, control);
}
@Test
public void testPoll()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.poll(), control.remove(0));
Assert.assertEquals(q, control);
}
@Test
public void testPollFirst()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.pollFirst(), control.remove(0));
Assert.assertEquals(q, control);
}
@Test
public void testPollLast()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.pollLast(), control.remove(control.size() - 1));
Assert.assertEquals(q, control);
}
@Test
public void testPeek()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.peek(), control.get(0));
Assert.assertEquals(q, control);
}
@Test
public void testPeekFirst()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.peekFirst(), control.get(0));
Assert.assertEquals(q, control);
}
@Test
public void testPeekLast()
{
List<Integer> control = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
LinkedDeque<Integer> q = new LinkedDeque<Integer>(control);
Assert.assertEquals(q.peekLast(), control.get(control.size() - 1));
Assert.assertEquals(q, control);
}
@Test
public void testEmptyRemove()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.remove();
Assert.fail("remove on empty queue should fail");
}
catch (NoSuchElementException e)
{
// Expected
}
}
@Test
public void testEmptyRemoveFirst()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.removeFirst();
Assert.fail("removeFirst on empty queue should fail");
}
catch (NoSuchElementException e)
{
// Expected
}
}
@Test
public void testEmptyRemoveLast()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.removeLast();
Assert.fail("removeLast on empty queue should fail");
}
catch (NoSuchElementException e)
{
// Expected
}
}
@Test
public void testEmptyPoll()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.poll(), "poll on empty queue should return null");
}
@Test
public void testEmptyPollFirst()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.pollFirst(), "pollFirst on empty queue should return null");
}
@Test
public void testEmptyPollLast()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.pollLast(), "pollLast on empty queue should return null");
}
@Test
public void testEmptyPeek()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.peek(), "peek on empty queue should return null");
}
@Test
public void testEmptyPeekFirst()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.peekFirst(), "peekFirst on empty queue should return null");
}
@Test
public void testEmptyPeekLast()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Assert.assertNull(q.peekLast(), "peekLast on empty queue should return null");
}
@Test
public void testAddNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.add(null);
Assert.fail("add null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testAddFirstNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.addFirst(null);
Assert.fail("addFirst null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testAddLastNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.addLast(null);
Assert.fail("addLast null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testOfferNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.offer(null);
Assert.fail("offer null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testOfferFirstNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.offerFirst(null);
Assert.fail("offerFirst null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testOfferLastNull()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
try
{
q.offerLast(null);
Assert.fail("offerLast null should have failed");
}
catch (NullPointerException e)
{
// expected
}
}
@Test
public void testForwardGeneral()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Queue<Object> control = new ArrayDeque<Object>();
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < i; j++)
{
Object o = new Object();
q.add(o);
control.add(o);
Assert.assertEquals(q, control);
}
for (int j = 0; j < i; j++)
{
Object o = q.remove();
Object o2 = control.remove();
Assert.assertEquals(o, o2);
Assert.assertEquals(q, control);
}
}
}
@Test
public void testReverseGeneral()
{
LinkedDeque<Object> q = new LinkedDeque<Object>();
Deque<Object> control = new ArrayDeque<Object>();
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < i; j++)
{
Object o = new Object();
q.addFirst(o);
control.addFirst(o);
Assert.assertEquals(q, control);
}
for (int j = 0; j < i; j++)
{
Object o = q.removeLast();
Object o2 = control.removeLast();
Assert.assertEquals(o, o2);
Assert.assertEquals(q, control);
}
}
}
@Test
public void testEquals()
{
List<Integer> list = Arrays.asList(1, 2, 3);
LinkedDeque<Integer> q = new LinkedDeque<Integer>(list);
Assert.assertEquals(q, list);
Assert.assertEquals(new LinkedDeque<Integer>(), Collections.emptyList());
Assert.assertNotSame(q, Collections.emptyList());
}
@Test
public void testEarlyRemoveFails()
{
LinkedDeque<Integer> q = new LinkedDeque<Integer>(Arrays.asList(1,2,3));
try
{
q.iterator().remove();
}
catch (IllegalStateException e)
{
// Expected
}
}
@Test
public void testDoubleRemoveFails()
{
LinkedDeque<Integer> q = new LinkedDeque<Integer>(Arrays.asList(1,2,3));
Iterator<Integer> i = q.iterator();
i.next();
i.remove();
try
{
i.remove();
}
catch (IllegalStateException e)
{
// Expected
}
}
@Test
public void testIteratorRemoveHead()
{
testIteratorRemoval(0, 3, true);
}
@Test
public void testIteratorRemoveMiddle()
{
testIteratorRemoval(1, 3, true);
}
@Test
public void testIteratorRemoveTail()
{
testIteratorRemoval(2, 3, true);
}
@Test
public void testIteratorRemoval()
{
for (int i = 1; i < 10; i++)
{
for (int j = 0; j < i; j++)
{
testIteratorRemoval(j, i, true);
}
}
}
@Test
public void testDescIteratorRemoveHead()
{
testIteratorRemoval(0, 3, false);
}
@Test
public void testDescIteratorRemoveMiddle()
{
testIteratorRemoval(1, 3, false);
}
@Test
public void testDescIteratorRemoveTail()
{
testIteratorRemoval(2, 3, false);
}
@Test
public void testDescIteratorRemoval()
{
for (int i = 1; i < 10; i++)
{
for (int j = 0; j < i; j++)
{
testIteratorRemoval(j, i, false);
}
}
}
private void testIteratorRemoval(int target, int size, boolean ascending)
{
try
{
List<Integer> list = new ArrayList<Integer>(size);
for (int i = 0; i < size; i++)
{
list.add(i);
}
LinkedDeque<Integer> q = new LinkedDeque<Integer>(list);
Iterator<Integer> it = (ascending ? q.iterator() : q.descendingIterator());
for (int i = 0; i < target + 1; i++)
{
it.next();
}
it.remove();
list.remove(ascending ? target : size - target - 1);
Assert.assertEquals(q, list, "Iterator " + (ascending ? "ascending" : "descending") +
" removal of " + target + " failed with list size " + size);
}
catch (Exception e)
{
Assert.fail("Iterator " + (ascending ? "ascending" : "descending") + " removal of " +
target + " failed with list size " + size, e);
}
}
// This tests the LinkedDeque-specific methods which remove nodes from the interior of the queue.
@Test
public void bigTest()
{
Random rand = new Random(9939393);
List<Object> control = new ArrayList<Object>();
List<LinkedDeque.Node<Object>> nodes = new ArrayList<LinkedDeque.Node<Object>>();
LinkedDeque<Object> queue =new LinkedDeque<Object>();
for (int i = 0; i < 100000; i++)
{
int r = rand.nextInt(10);
if (r < 6 || control.isEmpty())
{
Object o = new Object();
control.add(o);
nodes.add(queue.addLastNode(o));
}
else
{
int index = rand.nextInt(control.size());
Object o = control.remove(index);
LinkedDeque.Node<Object> node = nodes.remove(index);
Object o2 = queue.removeNode(node);
Assert.assertEquals(o, o2, "objects were not equal");
}
}
Assert.assertEquals(control.size(), nodes.size());
Assert.assertEquals(control.size(), queue.size());
int size = control.size();
for (int i = 0; i < size; i++)
{
Object o = control.remove(0);
Object o2 = queue.poll();
Assert.assertEquals(o, o2);
}
Assert.assertTrue(control.isEmpty());
Assert.assertTrue(queue.isEmpty());
}
}