/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.util;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
public final class FilteringIteratorTest {
@Test
public void correctUsageBasic() {
ArrayList<Integer> list = list(1, 2, 3, 4, 5, 6);
List<Integer> filtered = dump( onlyEvens(list) );
assertEquals("filtered list", list(2, 4, 6), filtered);
}
// have to filter out more than one in a row
@Test
public void correctUsageBasicSparse() {
ArrayList<Integer> list = list(1, 27, 31, 11, 2, 3, 4, 5, 6);
List<Integer> filtered = dump( onlyEvens(list) );
assertEquals("filtered list", list(2, 4, 6), filtered);
}
@Test
public void correctUsageEmptyList() {
List<Integer> filtered = dump( onlyEvens() );
assertEquals("filtered list", list(), filtered);
}
@Test
public void correctUsageEmptyAfterFilter() {
List<Integer> filtered = dump( onlyEvens(1, 3, 7) );
assertEquals("filtered list", list(), filtered);
}
@Test
public void correctUsageRemove() {
ArrayList<Integer> list = list(1, 2, 3, 4, 5, 6);
Iterator<Integer> iterator = onlyEvens(list, true);
List<Integer> removed = new ArrayList<>();
while (iterator.hasNext()) {
removed.add( iterator.next() );
iterator.remove();
}
assertEquals("removed", list(2, 4, 6), removed);
assertEquals("left", list(1, 3, 5), list);
}
@Test(expected=NoSuchElementException.class)
public void nextOnEmpty() {
Iterator<Integer> iterator = onlyEvens();
iterator.next();
}
@Test(expected=NoSuchElementException.class)
public void nextOnEmptyAfterFilter() {
Iterator<Integer> iterator = onlyEvens(1);
iterator.next();
}
@Test
public void nextTwice() {
Iterator<Integer> iterator = onlyEvens(1, 2, 3, 4, 5);
assertEquals("first", 2, iterator.next().intValue());
assertEquals("second", 4, iterator.next().intValue());
assertFalse("hasNext() == true", iterator.hasNext());
}
@Test(expected=IllegalStateException.class)
public void removeTwice() {
Iterator<Integer> iterator = SafeAction.of(new SafeAction.Get<Iterator<Integer>>() {
@Override
public Iterator<Integer> get() {
Iterator<Integer> iterator = onlyEvens(1, 2);
assertTrue("hasNext == false", iterator.hasNext());
assertEquals("next()", 2, iterator.next().intValue());
iterator.remove();
return iterator;
}
});
iterator.remove();
}
@Test(expected=UnsupportedOperationException.class)
public void removeDisallowedByIterator() {
Iterator<Integer> iterator = SafeAction.of(new SafeAction.Get<Iterator<Integer>>() {
@Override
public Iterator<Integer> get() {
Iterator<Integer> iterator = onlyEvens(list(2), false);
assertTrue("hasNext == false", iterator.hasNext());
assertEquals("next()", 2, iterator.next().intValue());
return iterator;
}
});
iterator.remove();
}
@Test(expected=UnsupportedOperationException.class)
public void removeDisallowedByDelegate() {
Iterator<Integer> iterator = SafeAction.of(new SafeAction.Get<Iterator<Integer>>() {
@Override
public Iterator<Integer> get() {
Iterator<Integer> iterator = onlyEvens(Collections.unmodifiableList(list(2)), false);
assertTrue("hasNext == false", iterator.hasNext());
assertEquals("next()", 2, iterator.next().intValue());
return iterator;
}
});
iterator.remove();
}
@Test
public void hasNextTwice() {
Iterator<Integer> iterator = onlyEvens(1, 2, 3);
assertTrue("hasNext 1", iterator.hasNext());
assertTrue("hasNext 2", iterator.hasNext());
assertEquals("next", 2, iterator.next().intValue());
assertFalse("hasNext 3", iterator.hasNext());
}
private static Iterator<Integer> onlyEvens(int... integers) {
return onlyEvens(list(integers));
}
private static Iterator<Integer> onlyEvens(Iterable<Integer> iterable) {
return onlyEvens(iterable, true);
}
private static Iterator<Integer> onlyEvens(Iterable<Integer> iterable, boolean mutable) {
return new FilteringIterator<Integer>(iterable.iterator(), mutable) {
@Override
protected boolean allow(Integer item) {
return (item % 2) == 0;
}
};
}
private static List<Integer> dump(Iterator<Integer> iterator) {
ArrayList<Integer> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
private static ArrayList<Integer> list(int... values) {
ArrayList<Integer> list = new ArrayList<>(values.length);
for (int value : values) {
list.add(value);
}
return list;
}
}