package com.googlecode.totallylazy.collections;
import com.googlecode.totallylazy.Lists;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.Pair;
import com.googlecode.totallylazy.predicates.Predicates;
import com.googlecode.totallylazy.Sequence;
import org.junit.Test;
import java.util.Iterator;
import java.util.NoSuchElementException;
import static com.googlecode.totallylazy.Option.none;
import static com.googlecode.totallylazy.Option.some;
import static com.googlecode.totallylazy.Pair.pair;
import static com.googlecode.totallylazy.predicates.Predicates.equalTo;
import static com.googlecode.totallylazy.Sequences.sequence;
import static com.googlecode.totallylazy.Strings.contains;
import static com.googlecode.totallylazy.matchers.IterableMatcher.hasExactly;
import static com.googlecode.totallylazy.matchers.Matchers.is;
import static com.googlecode.totallylazy.numbers.Numbers.add;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.fail;
public abstract class MapContract {
protected abstract <K extends Comparable<K>, V> MapFactory<K, V, ? extends PersistentMap<K, V>> factory();
protected <K extends Comparable<K>, V> PersistentMap<K, V> empty(Class<K> kClass, Class<V> vClass) {
return this.<K, V>factory().empty();
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> empty() {
return this.<K, V>factory().empty();
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map() {
return empty();
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(K key, V value) {
return this.<K, V>factory().map(key, value);
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(K key1, V value1, K key2, V value2) {
return this.<K, V>factory().map(key1, value1, key2, value2);
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(K key1, V value1, K key2, V value2, K key3, V value3) {
return this.<K, V>factory().map(key1, value1, key2, value2, key3, value3);
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4) {
return this.<K, V>factory().map(key1, value1, key2, value2, key3, value3, key4, value4);
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4, K key5, V value5) {
return this.<K, V>factory().map(key1, value1, key2, value2, key3, value3, key4, value4, key5, value5);
}
protected <K extends Comparable<K>, V> PersistentMap<K, V> map(Iterable<? extends Pair<K, V>> iterable) {
return this.<K, V>factory().map(iterable);
}
@Test
public void canGet() throws Exception {
PersistentMap<Integer, String> map = map(1, "Dan", 2, "Ray", 3, "Stu");
assertThat(map.lookup(2), is(some("Ray")));
assertThat(map.lookup(4), is(none(String.class)));
}
@Test
@SuppressWarnings("unchecked")
public void canPut() throws Exception {
PersistentMap<Integer, String> map = map(1, "Dan").insert(3, "Stu").insert(2, "Ray");
assertThat(map, containsInAnyOrder(pair(1, "Dan"), pair(3, "Stu"), pair(2, "Ray")));
}
@Test
@SuppressWarnings("unchecked")
public void canRemove() throws Exception {
final PersistentMap<Integer, String> map = map(4, "Alex", 1, "Dan", 3, "Stu", 2, "Ray");
assertThat(map.delete(4), containsInAnyOrder(pair(1, "Dan"), pair(3, "Stu"), pair(2, "Ray")));
assertThat(map.delete(3), containsInAnyOrder(pair(4, "Alex"), pair(1, "Dan"), pair(2, "Ray")));
assertThat(map.delete(2), containsInAnyOrder(pair(4, "Alex"), pair(1, "Dan"), pair(3, "Stu")));
assertThat(map.delete(1), containsInAnyOrder(pair(4, "Alex"), pair(3, "Stu"), pair(2, "Ray")));
assertThat(map.delete(0), is(map));
}
@Test
public void putReplacesValuesWithSameKey() throws Exception {
PersistentMap<Integer, String> map = map(1, "Dan").insert(3, "Stu").insert(1, "Ray");
assertThat(map, hasExactly(pair(1, "Ray"), pair(3, "Stu")));
}
@Test
public void canCheckContains() throws Exception {
PersistentMap<Integer, String> map = map(1, "Dan", 2, "Ray", 3, "Stu");
assertThat(map.contains(2), is(true));
assertThat(map.contains(4), is(false));
}
@Test
public void canCreateFromAnIterable() throws Exception {
PersistentMap<Integer, String> map = map(sequence(pair(1, "Dan"), pair(2, "Ray"), pair(3, "Stu")));
assertThat(map.contains(2), is(true));
assertThat(map.contains(4), is(false));
}
@Test
@SuppressWarnings("unchecked")
public void canConvertToPersistentList() throws Exception {
PersistentList<Pair<Integer, String>> map = map(2, "Ray", 1, "Dan", 3, "Stu").toPersistentList();
assertThat(map, containsInAnyOrder(pair(2, "Ray"), pair(1, "Dan"), pair(3, "Stu")));
}
@Test
@SuppressWarnings("unchecked")
public void canJoin() throws Exception {
PersistentMap<Integer, String> map = map(3, "Stu", 4, "Matt").joinTo(map(1, "Dan", 2, "Ray"));
assertThat(map, containsInAnyOrder(pair(1, "Dan"), pair(2, "Ray"), pair(3, "Stu"), pair(4, "Matt")));
}
@Test
public void canIterate() throws Exception {
final Iterator<Pair<Integer, Integer>> iterator = map(0, 0, 1, 1, 2, 2).iterator();
assertThat(iterator.hasNext(), is(true));
assertThat(iterator.next().first(), is(0));
assertThat(iterator.hasNext(), is(true));
assertThat(iterator.next().first(), is(1));
assertThat(iterator.hasNext(), is(true));
assertThat(iterator.next().first(), is(2));
assertThat(iterator.hasNext(), is(false));
}
@Test
public void canGetKeys() throws Exception {
Sequence<Integer> keys = map(4, "Alex", 1, "Dan", 3, "Stu", 2, "Ray").keys();
assertThat(keys, containsInAnyOrder(1,2,3,4));
}
@Test
public void supportsIsEmpty() throws Exception {
assertThat(empty(Integer.class, String.class).isEmpty(), is(true));
assertThat(map(1,"2").isEmpty(), is(false));
assertThat(map(1,"2").delete(1).isEmpty(), is(true));
}
@Test
public void supportsHead() throws Exception {
assertThat(map(1,"2").head(), is(pair(1, "2")));
try {
empty(Integer.class, String.class).head();
fail("NoSuchElementException expect on calling head on empty map");
} catch (NoSuchElementException ignore) {
}
}
@Test
public void supportsHeadOption() throws Exception {
assertThat(map(1,"2").headOption(), is(some(pair(1, "2"))));
assertThat(empty(Integer.class, String.class).headOption(), is(Option.<Pair<Integer, String >>none()));
}
@Test
public void supportsTail() throws Exception {
assertThat(map(1,"2").tail().isEmpty(), is(true));
}
@Test
@SuppressWarnings("unchecked")
public void supportsFold() throws Exception {
assertThat(map(1, "2").fold(Lists.list(pair(0, "1")), Lists.functions.<Pair<Integer, String>>add()), is(Lists.list(pair(0, "1"), pair(1, "2"))));
}
@Test
public void exists() throws Exception {
assertThat(map(1,"2").exists(equalTo(1)), is(true));
assertThat(map(1,"2").exists(equalTo(2)), is(false));
assertThat(empty(Integer.class, String.class).exists(equalTo(2)), is(false));
}
}