/*
* Copyright 2016 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 java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.Queue;
import java.util.function.Supplier;
import com.github.benmanes.caffeine.cache.AccessOrderDeque.AccessOrder;
import com.github.benmanes.caffeine.cache.WriteOrderDeque.WriteOrder;
import com.google.common.base.MoreObjects;
import com.google.common.collect.testing.MinimalCollection;
import com.google.common.collect.testing.QueueTestSuiteBuilder;
import com.google.common.collect.testing.SampleElements;
import com.google.common.collect.testing.TestQueueGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Guava testlib tests for the {@link LinkedDeque}.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
public final class LinkedDequeTests extends TestCase {
static final LinkedValue a = new LinkedValue("a");
static final LinkedValue b = new LinkedValue("b");
static final LinkedValue c = new LinkedValue("c");
static final LinkedValue d = new LinkedValue("d");
static final LinkedValue e = new LinkedValue("e");
// Due to stateful elements, tests calling resetCollection() for an comparable iterator will
// cause unexpected mutations. Instead a different collection type should be used for comparison
static boolean useTarget;
public static Test suite() throws Exception {
TestSuite suite = new TestSuite();
suite.addTest(suite("AccessOrderDeque", AccessOrderDeque::new));
suite.addTest(suite("WriteOrderDeque", WriteOrderDeque::new));
return suite;
}
protected static Test suite(String name, Supplier<LinkedDeque<LinkedValue>> supplier) {
return QueueTestSuiteBuilder
.using(new TestLinkedValueGenerator() {
@Override public Queue<LinkedValue> create(LinkedValue[] elements) {
Deque<LinkedValue> deque = useTarget ? supplier.get() : new ArrayDeque<>();
deque.addAll(MinimalCollection.of(elements));
useTarget = false;
return deque;
}
})
.named(name)
.withFeatures(
CollectionFeature.ALLOWS_NULL_QUERIES,
CollectionFeature.GENERAL_PURPOSE,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.withSetUp(() -> useTarget = true)
.withTearDown(() -> {
Arrays.asList(a, b, c, d, e).forEach(value -> {
value.setNextInAccessOrder(null);
value.setPreviousInAccessOrder(null);
});
})
.createTestSuite();
}
/** See TestStringQueueGenerator */
static abstract class TestLinkedValueGenerator implements TestQueueGenerator<LinkedValue> {
@Override
public SampleElements<LinkedValue> samples() {
return new SampleElements<LinkedValue>(b, a, c, d, e);
}
@Override
public Queue<LinkedValue> create(Object... elements) {
LinkedValue[] array = new LinkedValue[elements.length];
int i = 0;
for (Object e : elements) {
array[i++] = (LinkedValue) e;
}
return create(array);
}
protected abstract Queue<LinkedValue> create(LinkedValue[] elements);
@Override
public LinkedValue[] createArray(int length) {
return new LinkedValue[length];
}
@Override
public List<LinkedValue> order(List<LinkedValue> insertionOrder) {
return insertionOrder;
}
}
static final class LinkedValue implements AccessOrder<LinkedValue>, WriteOrder<LinkedValue> {
final String value;
LinkedValue prev;
LinkedValue next;
LinkedValue(String 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.equals(((LinkedValue) o).value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("value", value)
.add("prev", (prev == null) ? null : prev.value)
.add("next", (next == null) ? null : next.value)
.toString();
}
}
}