/*
* Copyright 2014 Ben Manes. All Rights Reserved.
*
* 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.
*/
package com.github.benmanes.caffeine.cache;
import static com.github.benmanes.caffeine.testing.IsEmptyIterable.deeplyEmpty;
import static com.google.common.collect.Iterators.elementsEqual;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.NoSuchElementException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.github.benmanes.caffeine.cache.AccessOrderDeque.AccessOrder;
import com.github.benmanes.caffeine.cache.LinkedDeque.PeekingIterator;
import com.github.benmanes.caffeine.cache.WriteOrderDeque.WriteOrder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
/**
* A unit-test for the @{@link AbstractLinkedDeque} implementations.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
public final class LinkedDequeTest {
static final int SIZE = 100;
@Test(dataProvider = "empty")
public void clear_whenEmpty(Deque<?> deque) {
deque.clear();
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "full")
public void clear_whenPopulated(Deque<?> deque) {
deque.clear();
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void isEmpty_whenEmpty(Deque<?> deque) {
assertThat(deque.isEmpty(), is(true));
}
@Test(dataProvider = "full")
public void isEmpty_whenPopulated(Deque<?> deque) {
assertThat(deque.isEmpty(), is(false));
}
@Test(dataProvider = "empty")
public void size_whenEmpty(Deque<?> deque) {
assertThat(deque.size(), is(0));
}
@Test(dataProvider = "full")
public void size_whenPopulated(Deque<?> deque) {
assertThat(deque.size(), is(SIZE));
assertThat(Iterables.size(deque), is(SIZE));
}
@Test(dataProvider = "empty")
public void contains_withNull(Deque<?> deque) {
assertThat(deque.contains(null), is(false));
}
@Test(dataProvider = "full")
public void contains_whenFound(LinkedDeque<LinkedValue> deque) {
assertThat(deque.contains(Iterables.get(deque, SIZE / 2)), is(true));
}
@Test(dataProvider = "full")
public void contains_whenNotFound(LinkedDeque<LinkedValue> deque) {
LinkedValue unlinked = new LinkedValue(1);
assertThat(deque.contains(unlinked), is(false));
}
/* ---------------- Move -------------- */
@Test(dataProvider = "full")
public void moveToFront_first(LinkedDeque<LinkedValue> deque) {
checkMoveToFront(deque, deque.getFirst());
}
@Test(dataProvider = "full")
public void moveToFront_middle(LinkedDeque<LinkedValue> deque) {
checkMoveToFront(deque, Iterables.get(deque, SIZE / 2));
}
@Test(dataProvider = "full")
public void moveToFront_last(LinkedDeque<LinkedValue> deque) {
checkMoveToFront(deque, deque.getLast());
}
private void checkMoveToFront(LinkedDeque<LinkedValue> deque, LinkedValue element) {
deque.moveToFront(element);
assertThat(deque.peekFirst(), is(element));
assertThat(deque.size(), is(SIZE));
}
@Test(dataProvider = "full")
public void moveToBack_first(LinkedDeque<LinkedValue> deque) {
checkMoveToBack(deque, deque.getFirst());
}
@Test(dataProvider = "full")
public void moveToBack_middle(LinkedDeque<LinkedValue> deque) {
checkMoveToBack(deque, Iterables.get(deque, SIZE / 2));
}
@Test(dataProvider = "full")
public void moveToBack_last(LinkedDeque<LinkedValue> deque) {
checkMoveToBack(deque, deque.getLast());
}
private void checkMoveToBack(LinkedDeque<LinkedValue> deque, LinkedValue element) {
deque.moveToBack(element);
assertThat(deque.size(), is(SIZE));
assertThat(deque.getLast(), is(element));
}
/* ---------------- First / Last -------------- */
@Test(dataProvider = "empty")
public void isFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.isFirst(new LinkedValue(0)), is(false));
assertThat(deque.isFirst(null), is(false));
}
@Test(dataProvider = "full")
public void isFirst_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.first;
assertThat(deque.isFirst(first), is(true));
assertThat(deque.first, is(first));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(first), is(true));
}
@Test(dataProvider = "empty")
public void isLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.isLast(new LinkedValue(0)), is(false));
assertThat(deque.isLast(null), is(false));
}
@Test(dataProvider = "full")
public void isLast_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue last = deque.last;
assertThat(deque.isLast(last), is(true));
assertThat(deque.last, is(last));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(last), is(true));
}
/* ---------------- Peek -------------- */
@Test(dataProvider = "empty")
public void peek_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.peek(), is(nullValue()));
}
@Test(dataProvider = "full")
public void peek_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.first;
assertThat(deque.peek(), is(first));
assertThat(deque.first, is(first));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(first), is(true));
}
@Test(dataProvider = "empty")
public void peekFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.peekFirst(), is(nullValue()));
}
@Test(dataProvider = "full")
public void peekFirst_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.first;
assertThat(deque.peekFirst(), is(first));
assertThat(deque.first, is(first));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(first), is(true));
}
@Test(dataProvider = "empty")
public void peekLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.peekLast(), is(nullValue()));
}
@Test(dataProvider = "full")
public void peekLast_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue last = deque.last;
assertThat(deque.peekLast(), is(last));
assertThat(deque.last, is(last));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(last), is(true));
}
/* ---------------- Get -------------- */
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void getFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.getFirst();
}
@Test(dataProvider = "full")
public void getFirst_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.first;
assertThat(deque.getFirst(), is(first));
assertThat(deque.first, is(first));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(first), is(true));
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void getLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.getLast();
}
@Test(dataProvider = "full")
public void getLast_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue last = deque.last;
assertThat(deque.getLast(), is(last));
assertThat(deque.last, is(last));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(last), is(true));
}
/* ---------------- Element -------------- */
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void element_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.element();
}
@Test(dataProvider = "full")
public void element_whenPopulated(AbstractLinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.first;
assertThat(deque.element(), is(first));
assertThat(deque.first, is(first));
assertThat(deque, hasSize(SIZE));
assertThat(deque.contains(first), is(true));
}
/* ---------------- Offer -------------- */
@Test(dataProvider = "empty")
public void offer_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
assertThat(deque.offer(value), is(true));
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void offer_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
assertThat(deque.offer(value), is(true));
assertThat(deque.peekFirst(), is(not(value)));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full")
public void offer_whenLinked(LinkedDeque<LinkedValue> deque) {
assertThat(deque.offer(deque.peek()), is(false));
assertThat(deque, hasSize(SIZE));
}
@Test(dataProvider = "empty")
public void offerFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
assertThat(deque.offerFirst(value), is(true));
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void offerFirst_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
assertThat(deque.offerFirst(value), is(true));
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(not(value)));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full")
public void offerFirst_whenLinked(LinkedDeque<LinkedValue> deque) {
assertThat(deque.offerFirst(deque.peek()), is(false));
assertThat(deque, hasSize(SIZE));
}
@Test(dataProvider = "empty")
public void offerLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
assertThat(deque.offerLast(value), is(true));
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void offerLast_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
assertThat(deque.offerLast(value), is(true));
assertThat(deque.peekFirst(), is(not(value)));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full")
public void offerLast_whenLinked(LinkedDeque<LinkedValue> deque) {
assertThat(deque.offerLast(deque.peek()), is(false));
assertThat(deque, hasSize(SIZE));
}
/* ---------------- Add -------------- */
@Test(dataProvider = "empty")
public void add_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
assertThat(deque.add(value), is(true));
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void add_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
assertThat(deque.add(value), is(true));
assertThat(deque.peekFirst(), is(not(value)));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full")
public void add_whenLinked(LinkedDeque<LinkedValue> deque) {
assertThat(deque.add(deque.peek()), is(false));
}
@Test(dataProvider = "empty")
public void addFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
deque.addFirst(value);
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void addFirst_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
deque.addFirst(value);
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(not(value)));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full", expectedExceptions = IllegalArgumentException.class)
public void addFirst_whenLinked(LinkedDeque<LinkedValue> deque) {
deque.addFirst(deque.peek());
}
@Test(dataProvider = "empty")
public void addLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
deque.addLast(value);
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void addLast_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
deque.addLast(value);
assertThat(deque.peekFirst(), is(not(value)));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full", expectedExceptions = IllegalArgumentException.class)
public void addLast_whenLinked(LinkedDeque<LinkedValue> deque) {
deque.addLast(deque.peek());
}
@Test(dataProvider = "empty")
public void addAll_withEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.addAll(ImmutableList.<LinkedValue>of()), is(false));
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void addAll_withPopulated(LinkedDeque<LinkedValue> deque) {
List<LinkedValue> expected = new ArrayList<>();
populate(expected);
assertThat(deque.addAll(expected), is(true));
assertThat(deque, contains(expected.toArray(new LinkedValue[0])));
}
@Test(dataProvider = "full")
@SuppressWarnings("ModifyingCollectionWithItself")
public void addAll_withSelf(LinkedDeque<LinkedValue> deque) {
assertThat(deque.addAll(deque), is(false));
}
/* ---------------- Poll -------------- */
@Test(dataProvider = "empty")
public void poll_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.poll(), is(nullValue()));
}
@Test(dataProvider = "full")
public void poll_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peek();
assertThat(deque.poll(), is(first));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void poll_toEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value;
while ((value = deque.poll()) != null) {
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void pollFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.pollFirst(), is(nullValue()));
}
@Test(dataProvider = "full")
public void pollFirst_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.pollFirst(), is(first));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void pollFirst_toEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value;
while ((value = deque.pollFirst()) != null) {
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void pollLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.pollLast(), is(nullValue()));
}
@Test(dataProvider = "full")
public void pollLast_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue last = deque.peekLast();
assertThat(deque.pollLast(), is(last));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(last), is(false));
}
@Test(dataProvider = "full")
public void pollLast_toEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value;
while ((value = deque.pollLast()) != null) {
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
/* ---------------- Remove -------------- */
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void remove_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.remove();
}
@Test(dataProvider = "full")
public void remove_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.remove(), is(first));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void remove_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.remove();
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void removeElement_notFound(LinkedDeque<LinkedValue> deque) {
assertThat(deque.remove(new LinkedValue(0)), is(false));
}
@Test(dataProvider = "full")
public void removeElement_whenFound(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.remove(first), is(true));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void removeElement_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.peek();
assertThat(deque.remove(value), is(true));
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void removeFirst_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.removeFirst();
}
@Test(dataProvider = "full")
public void removeFirst_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.removeFirst(), is(first));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void removeFirst_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.removeFirst();
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void removeLast_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.removeLast();
}
@Test(dataProvider = "full")
public void removeLast_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue last = deque.peekLast();
assertThat(deque.removeLast(), is(last));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(last), is(false));
}
@Test(dataProvider = "full")
public void removeLast_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.removeLast();
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void removeFirstOccurrence_notFound(LinkedDeque<LinkedValue> deque) {
assertThat(deque.removeFirstOccurrence(new LinkedValue(0)), is(false));
}
@Test(dataProvider = "full")
public void removeFirstOccurrence_whenFound(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.removeFirstOccurrence(first), is(true));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void removeFirstOccurrence_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.peek();
assertThat(deque.removeFirstOccurrence(value), is(true));
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void removeLastOccurrence_notFound(LinkedDeque<LinkedValue> deque) {
assertThat(deque.removeLastOccurrence(new LinkedValue(0)), is(false));
}
@Test(dataProvider = "full")
public void removeLastOccurrence_whenFound(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.removeLastOccurrence(first), is(true));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void removeLastOccurrence_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.peek();
assertThat(deque.removeLastOccurrence(value), is(true));
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "empty")
public void removeAll_withEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.removeAll(ImmutableList.of()), is(false));
assertThat(deque, is(deeplyEmpty()));
}
@Test(dataProvider = "full")
public void remove_withPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.removeAll(ImmutableList.of(first)), is(true));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void removeAll_toEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.removeAll(ImmutableList.copyOf(deque)), is(true));
assertThat(deque, is(deeplyEmpty()));
}
/* ---------------- Stack -------------- */
@Test(dataProvider = "empty")
public void push_whenEmpty(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(1);
deque.push(value);
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(value));
assertThat(deque, hasSize(1));
}
@Test(dataProvider = "full")
public void push_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue value = new LinkedValue(SIZE);
deque.push(value);
assertThat(deque.peekFirst(), is(value));
assertThat(deque.peekLast(), is(not(value)));
assertThat(deque, hasSize(SIZE + 1));
}
@Test(dataProvider = "full", expectedExceptions = IllegalArgumentException.class)
public void push_whenLinked(LinkedDeque<LinkedValue> deque) {
deque.push(deque.peek());
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void pop_whenEmpty(LinkedDeque<LinkedValue> deque) {
deque.pop();
}
@Test(dataProvider = "full")
public void pop_whenPopulated(LinkedDeque<LinkedValue> deque) {
LinkedValue first = deque.peekFirst();
assertThat(deque.pop(), is(first));
assertThat(deque, hasSize(SIZE - 1));
assertThat(deque.contains(first), is(false));
}
@Test(dataProvider = "full")
public void pop_toEmpty(LinkedDeque<LinkedValue> deque) {
while (!deque.isEmpty()) {
LinkedValue value = deque.pop();
assertThat(deque.contains(value), is(false));
}
assertThat(deque, is(deeplyEmpty()));
}
/* ---------------- Iterators -------------- */
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void iterator_noMoreElements(LinkedDeque<LinkedValue> deque) {
deque.iterator().next();
}
@Test(dataProvider = "empty")
public void iterator_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.iterator().peek(), is(nullValue()));
assertThat(deque.iterator().hasNext(), is(false));
}
@Test(dataProvider = "full")
public void iterator_whenWarmed(LinkedDeque<LinkedValue> deque) {
List<LinkedValue> expected = new ArrayList<>();
populate(expected);
assertThat(deque.peek(), is(not(nullValue())));
assertThat(elementsEqual(deque.iterator(), expected.iterator()), is(true));
}
@Test(dataProvider = "full")
public void iterator_removal(LinkedDeque<LinkedValue> deque) {
PeekingIterator<LinkedValue> iterator = deque.iterator();
LinkedValue value = iterator.next();
iterator.remove();
int remaining = 0;
while (iterator.hasNext()) {
assertThat(iterator.next(), is(not(value)));
remaining++;
}
assertThat(remaining, is(SIZE - 1));
assertThat(deque, hasSize(SIZE - 1));
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void descendingIterator_noMoreElements(LinkedDeque<LinkedValue> deque) {
deque.descendingIterator().next();
}
@Test(dataProvider = "empty")
public void descendingIterator_whenEmpty(LinkedDeque<LinkedValue> deque) {
assertThat(deque.descendingIterator().peek(), is(nullValue()));
assertThat(deque.descendingIterator().hasNext(), is(false));
}
@Test(dataProvider = "full")
public void descendingIterator_whenWarmed(LinkedDeque<LinkedValue> deque) {
List<LinkedValue> expected = new ArrayList<>();
populate(expected);
Collections.reverse(expected);
assertThat(deque.descendingIterator().peek(), is(not(nullValue())));
assertThat(elementsEqual(deque.descendingIterator(), expected.iterator()), is(true));
}
@Test(dataProvider = "full")
public void descendingIterator_removal(LinkedDeque<LinkedValue> deque) {
PeekingIterator<LinkedValue> iterator = deque.descendingIterator();
LinkedValue value = iterator.next();
iterator.remove();
int remaining = 0;
while (iterator.hasNext()) {
assertThat(iterator.next(), is(not(value)));
remaining++;
}
assertThat(remaining, is(SIZE - 1));
assertThat(deque, hasSize(SIZE - 1));
}
@Test(dataProvider = "full")
public void concat(LinkedDeque<LinkedValue> deque) {
List<LinkedValue> expect = ImmutableList.copyOf(
Iterators.concat(deque.iterator(), deque.descendingIterator()));
Iterable<LinkedValue> actual = () -> PeekingIterator.concat(
deque.iterator(), deque.descendingIterator());
assertThat(actual, contains(expect.toArray(new LinkedValue[0])));
}
@Test(dataProvider = "empty", expectedExceptions = NoSuchElementException.class)
public void concat_noMoreElements(LinkedDeque<LinkedValue> deque) {
PeekingIterator.concat(deque.iterator(), deque.iterator()).next();
}
@Test(dataProvider = "full")
public void comparing(LinkedDeque<LinkedValue> deque) {
List<LinkedValue> expect = ImmutableList.copyOf(
Iterators.concat(deque.iterator(), deque.descendingIterator()));
PeekingIterator<LinkedValue> actual = PeekingIterator.comparing(
deque.iterator(), deque.descendingIterator(), (a, b) -> 1);
assertThat(actual.peek(), is(expect.get(0)));
assertThat((Iterable<LinkedValue>) () -> actual, contains(expect.toArray(new LinkedValue[0])));
}
@Test(dataProvider = "full")
public void comparing_uneven(LinkedDeque<LinkedValue> deque) {
PeekingIterator<LinkedValue> empty = new AccessOrderDeque<LinkedValue>().iterator();
PeekingIterator<?> left = PeekingIterator.comparing(deque.iterator(), empty, (a, b) -> 1);
PeekingIterator<?> right = PeekingIterator.comparing(deque.iterator(), empty, (a, b) -> 1);
assertThat(left.peek(), is(deque.getFirst()));
assertThat(right.peek(), is(deque.getFirst()));
}
/* ---------------- Deque providers -------------- */
@DataProvider(name = "empty")
public Object[][] providesEmptyDeque() {
return new Object[][] {
{ new AccessOrderDeque<LinkedValue>() },
{ new WriteOrderDeque<LinkedValue>() },
};
}
@DataProvider(name = "full")
public Object[][] providesWarmedDeque() {
Deque<LinkedValue> accessOrder = new AccessOrderDeque<LinkedValue>();
Deque<LinkedValue> writeOrder = new WriteOrderDeque<LinkedValue>();
populate(accessOrder);
populate(writeOrder);
return new Object[][] { { accessOrder }, { writeOrder }};
}
void populate(Collection<LinkedValue> collection) {
for (int i = 0; i < SIZE; i++) {
collection.add(new LinkedValue(i));
}
}
static final class LinkedValue implements AccessOrder<LinkedValue>, WriteOrder<LinkedValue> {
LinkedValue prev;
LinkedValue next;
final int value;
LinkedValue(int value) {
this.value = value;
}
@Override
public LinkedValue getPreviousInAccessOrder() {
return prev;
}
@Override
public void setPreviousInAccessOrder(LinkedValue prev) {
this.prev = prev;
}
@Override
public LinkedValue getNextInAccessOrder() {
return next;
}
@Override
public void setNextInAccessOrder(LinkedValue next) {
this.next = next;
}
@Override
public LinkedValue getPreviousInWriteOrder() {
return prev;
}
@Override
public void setPreviousInWriteOrder(LinkedValue prev) {
this.prev = prev;
}
@Override
public LinkedValue getNextInWriteOrder() {
return next;
}
@Override
public void setNextInWriteOrder(LinkedValue next) {
this.next = next;
}
@Override
public boolean equals(Object o) {
return (o instanceof LinkedValue) && (value == ((LinkedValue) o).value);
}
@Override
public int hashCode() {
return value;
}
@Override
public String toString() {
return String.format("value=%s prev=%s, next=%s]", value,
(prev == null) ? null : prev.value,
(next == null) ? null : next.value);
}
}
}