f81e1def8f
Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Reviewed-by: mcimadamore
197 lines
7.0 KiB
Java
197 lines
7.0 KiB
Java
/*
|
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code 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 General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8303882
|
|
* @summary Verify that Iterators method work as expected
|
|
* @modules jdk.compiler/com.sun.tools.javac.util
|
|
* @run junit IteratorsTest
|
|
*/
|
|
|
|
import com.sun.tools.javac.util.Iterators;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.NoSuchElementException;
|
|
import java.util.function.Function;
|
|
import org.junit.jupiter.api.*;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
|
public class IteratorsTest {
|
|
|
|
@Test
|
|
public void consistentNext() {
|
|
Iterator<?> emptyCompoundIterator = Iterators.createCompoundIterator(List.of(), Function.identity());
|
|
Assertions.assertThrows(NoSuchElementException.class, emptyCompoundIterator::next);
|
|
Assertions.assertThrows(NoSuchElementException.class, emptyCompoundIterator::next);
|
|
}
|
|
|
|
// different ways of obtaining an empty iterator are used to make sure
|
|
// the compound iterator doesn't depend on (checking) the identity of
|
|
// any one of them
|
|
@Test
|
|
public void intermediateEmptyIterators() {
|
|
List<Iterator<String>> inputs = List.of(
|
|
Collections.<String>emptyList().iterator(),
|
|
Collections.emptyListIterator(),
|
|
Collections.emptyIterator(),
|
|
List.of("1").iterator(),
|
|
List.of("2", "3").iterator(),
|
|
List.<String>of().iterator(),
|
|
Collections.<String>emptySet().iterator(),
|
|
List.of("4", "5").iterator(),
|
|
com.sun.tools.javac.util.List.<String>nil().iterator());
|
|
Iterator<String> emptyCompoundIterator = Iterators.createCompoundIterator(inputs, Function.identity());
|
|
var actual = new ArrayList<String>();
|
|
emptyCompoundIterator.forEachRemaining(actual::add);
|
|
assertEquals(List.of("1", "2", "3", "4", "5"), actual);
|
|
}
|
|
|
|
@Test
|
|
public void recursiveEmpty() {
|
|
Iterable<Iterator<Object>> inner = () -> Iterators.createCompoundIterator(List.of(), i -> Collections.emptyIterator());
|
|
Iterator<Object> outer = Iterators.createCompoundIterator(inner, Function.identity());
|
|
assertFalse(outer.hasNext());
|
|
}
|
|
|
|
@Test
|
|
public void compoundIterator() {
|
|
TestConverter<String> c = new TestConverter<>(it -> it);
|
|
TestIterator<String> test1 = new TestIterator<>(List.of("1").iterator());
|
|
TestIterator<String> test2 = new TestIterator<>(List.of("2").iterator());
|
|
Iterator<String> compound = Iterators.createCompoundIterator(List.of(test1, test2), c);
|
|
|
|
//nothing should be called before the hasNext or next is called:
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 0, 0);
|
|
assertAndResetMaxCalls(test2, 0, 0);
|
|
|
|
//when hasNext is called, should invoke the hasNext delegate once:
|
|
Assertions.assertTrue(compound.hasNext());
|
|
|
|
assertAndResetMaxCalls(c, 1);
|
|
assertAndResetMaxCalls(test1, 1, 0);
|
|
assertAndResetMaxCalls(test2, 0, 0);
|
|
|
|
Assertions.assertTrue(compound.hasNext());
|
|
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 1, 0);
|
|
assertAndResetMaxCalls(test2, 0, 0);
|
|
|
|
//next may invoke hasNext once:
|
|
Assertions.assertEquals("1", compound.next());
|
|
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 1, 1);
|
|
assertAndResetMaxCalls(test2, 0, 0);
|
|
|
|
Assertions.assertTrue(compound.hasNext());
|
|
|
|
assertAndResetMaxCalls(c, 1);
|
|
assertAndResetMaxCalls(test1, 1, 0);
|
|
assertAndResetMaxCalls(test2, 1, 0);
|
|
|
|
Assertions.assertTrue(compound.hasNext());
|
|
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 0, 0);
|
|
assertAndResetMaxCalls(test2, 1, 0);
|
|
|
|
Assertions.assertEquals("2", compound.next());
|
|
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 0, 0);
|
|
assertAndResetMaxCalls(test2, 1, 1);
|
|
|
|
Assertions.assertFalse(compound.hasNext());
|
|
|
|
assertAndResetMaxCalls(c, 0);
|
|
assertAndResetMaxCalls(test1, 0, 0);
|
|
assertAndResetMaxCalls(test2, 1, 0);
|
|
}
|
|
|
|
private void assertAndResetMaxCalls(TestIterator<?> test, int maxExpectedHasNextCalls, int maxExpectedNextCalls) {
|
|
if (test.hasNextCalls > maxExpectedHasNextCalls) {
|
|
Assertions.fail("too many hasNext invocations: " + test.hasNextCalls +
|
|
", expected: " + maxExpectedHasNextCalls);
|
|
}
|
|
test.hasNextCalls = 0;
|
|
if (test.nextCalls > maxExpectedNextCalls) {
|
|
Assertions.fail("too many next invocations: " + test.nextCalls +
|
|
", expected: " + maxExpectedNextCalls);
|
|
}
|
|
test.nextCalls = 0;
|
|
}
|
|
|
|
private void assertAndResetMaxCalls(TestConverter<?> test, int maxExpectedApplyCalls) {
|
|
if (test.applyCalls > maxExpectedApplyCalls) {
|
|
Assertions.fail("too many apply invocations: " + test.applyCalls +
|
|
", expected: " + maxExpectedApplyCalls);
|
|
}
|
|
test.applyCalls = 0;
|
|
}
|
|
|
|
static class TestIterator<T> implements Iterator<T> {
|
|
int hasNextCalls;
|
|
int nextCalls;
|
|
final Iterator<T> delegate;
|
|
|
|
public TestIterator(Iterator<T> delegate) {
|
|
this.delegate = delegate;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasNext() {
|
|
hasNextCalls++;
|
|
return delegate.hasNext();
|
|
}
|
|
|
|
@Override
|
|
public T next() {
|
|
nextCalls++;
|
|
return delegate.next();
|
|
}
|
|
}
|
|
|
|
static class TestConverter<T> implements Function<TestIterator<T>, Iterator<T>> {
|
|
int applyCalls;
|
|
final Function<TestIterator<T>, Iterator<T>> delegate;
|
|
|
|
public TestConverter(Function<TestIterator<T>, Iterator<T>> delegate) {
|
|
this.delegate = delegate;
|
|
}
|
|
|
|
@Override
|
|
public Iterator<T> apply(TestIterator<T> t) {
|
|
applyCalls++;
|
|
return delegate.apply(t);
|
|
}
|
|
}
|
|
}
|