diff --git a/pom.xml b/pom.xml index 9ad4475d30..7f639e5c2f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.baidu.hugegraph hugegraph-common - 1.7.1 + 1.7.2 hugegraph-common https://github.com/hugegraph/hugegraph-common @@ -218,7 +218,7 @@ - 1.7.1.0 + 1.7.2.0 diff --git a/src/main/java/com/baidu/hugegraph/iterator/BatchMapperIterator.java b/src/main/java/com/baidu/hugegraph/iterator/BatchMapperIterator.java new file mode 100644 index 0000000000..6b2a9135f9 --- /dev/null +++ b/src/main/java/com/baidu/hugegraph/iterator/BatchMapperIterator.java @@ -0,0 +1,103 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.baidu.hugegraph.iterator; + +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; + +import com.baidu.hugegraph.util.E; +import com.baidu.hugegraph.util.InsertionOrderUtil; +import com.google.common.collect.ImmutableList; + +public class BatchMapperIterator extends WrappedIterator { + + private final int batch; + private final Iterator originIterator; + private final Function, Iterator> mapperCallback; + + private Iterator batchIterator; + + public BatchMapperIterator(int batch, Iterator origin, + Function, Iterator> mapper) { + E.checkArgument(batch > 0, "Expect batch > 0, but got %s", batch); + this.batch = batch; + this.originIterator = origin; + this.mapperCallback = mapper; + this.batchIterator = null; + } + + @Override + protected Iterator originIterator() { + return this.originIterator; + } + + @Override + protected final boolean fetch() { + if (this.batchIterator != null && this.fetchFromBatch()) { + return true; + } + + List list = this.nextBatch(); + if (!list.isEmpty()) { + assert this.batchIterator == null; + // Do fetch + this.batchIterator = this.mapperCallback.apply(list); + if (this.batchIterator != null && this.fetchFromBatch()) { + return true; + } + } + return false; + } + + protected final List nextBatch() { + if (!this.originIterator.hasNext()) { + return ImmutableList.of(); + } + List list = InsertionOrderUtil.newList(); + for (int i = 0; i < this.batch && this.originIterator.hasNext(); i++) { + T next = this.originIterator.next(); + list.add(next); + } + return list; + } + + protected final boolean fetchFromBatch() { + E.checkNotNull(this.batchIterator, "mapper results"); + while (this.batchIterator.hasNext()) { + R result = this.batchIterator.next(); + if (result != null) { + assert this.current == none(); + this.current = result; + return true; + } + } + this.resetBatchIterator(); + return false; + } + + protected final void resetBatchIterator() { + if (this.batchIterator == null) { + return; + } + close(this.batchIterator); + this.batchIterator = null; + } +} diff --git a/src/main/java/com/baidu/hugegraph/iterator/IterableIterator.java b/src/main/java/com/baidu/hugegraph/iterator/CIter.java similarity index 60% rename from src/main/java/com/baidu/hugegraph/iterator/IterableIterator.java rename to src/main/java/com/baidu/hugegraph/iterator/CIter.java index eb2a966377..35eda45272 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/IterableIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/CIter.java @@ -21,32 +21,5 @@ import java.util.Iterator; -public class IterableIterator implements Iterator { - - private final Iterable iterable; - private final Iterator iterator; - - public IterableIterator(Iterable iterable) { - this.iterable = iterable; - this.iterator = iterable.iterator(); - } - - @Override - public boolean hasNext() { - return this.iterator.hasNext(); - } - - @Override - public T next() { - return this.iterator.next(); - } - - @Override - public void remove() { - this.iterator.remove(); - } - - public Iterable iterable() { - return iterable; - } +public interface CIter extends Iterator, AutoCloseable, Metadatable { } diff --git a/src/main/java/com/baidu/hugegraph/iterator/ExtendableIterator.java b/src/main/java/com/baidu/hugegraph/iterator/ExtendableIterator.java index 7d036111ae..d9985edc53 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/ExtendableIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/ExtendableIterator.java @@ -19,10 +19,8 @@ package com.baidu.hugegraph.iterator; -import java.util.ArrayList; import java.util.Deque; import java.util.Iterator; -import java.util.List; import java.util.concurrent.ConcurrentLinkedDeque; import com.baidu.hugegraph.util.E; @@ -30,13 +28,11 @@ public class ExtendableIterator extends WrappedIterator { private final Deque> itors; - private final List> removedItors; private Iterator currentIterator; public ExtendableIterator() { this.itors = new ConcurrentLinkedDeque<>(); - this.removedItors = new ArrayList<>(); this.currentIterator = null; } @@ -62,11 +58,6 @@ public ExtendableIterator extend(Iterator iter) { @Override public void close() throws Exception { - for (Iterator iter : this.removedItors) { - if (iter instanceof AutoCloseable) { - ((AutoCloseable) iter).close(); - } - } for (Iterator iter : this.itors) { if (iter instanceof AutoCloseable) { ((AutoCloseable) iter).close(); @@ -75,7 +66,7 @@ public void close() throws Exception { } @Override - protected Iterator originIterator() { + protected Iterator originIterator() { return this.currentIterator; } @@ -98,7 +89,7 @@ protected boolean fetch() { // The last one return false; } - this.removedItors.add(this.itors.removeFirst()); + close(this.itors.removeFirst()); } assert first != null && first.hasNext(); diff --git a/src/main/java/com/baidu/hugegraph/iterator/FlatMapperFilterIterator.java b/src/main/java/com/baidu/hugegraph/iterator/FlatMapperFilterIterator.java index 6046dd25a0..a222319b13 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/FlatMapperFilterIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/FlatMapperFilterIterator.java @@ -36,17 +36,17 @@ public FlatMapperFilterIterator(Iterator origin, } @Override - protected final boolean fetchMapped() { - E.checkNotNull(this.results, "mapper results"); - while (this.results.hasNext()) { - R result = this.results.next(); + protected final boolean fetchFromBatch() { + E.checkNotNull(this.batchIterator, "mapper results"); + while (this.batchIterator.hasNext()) { + R result = this.batchIterator.next(); if (result != null && this.filterCallback.apply(result)) { assert this.current == none(); this.current = result; return true; } } - this.results = null; + this.resetBatchIterator(); return false; } } diff --git a/src/main/java/com/baidu/hugegraph/iterator/FlatMapperIterator.java b/src/main/java/com/baidu/hugegraph/iterator/FlatMapperIterator.java index 9d50d79c5b..6b4cd9855b 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/FlatMapperIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/FlatMapperIterator.java @@ -29,48 +29,63 @@ public class FlatMapperIterator extends WrappedIterator { private final Iterator originIterator; private final Function> mapperCallback; - protected Iterator results; + protected Iterator batchIterator; public FlatMapperIterator(Iterator origin, Function> mapper) { this.originIterator = origin; this.mapperCallback = mapper; - this.results = null; + this.batchIterator = null; } @Override - protected Iterator originIterator() { + public void close() throws Exception { + this.resetBatchIterator(); + super.close(); + } + + @Override + protected Iterator originIterator() { return this.originIterator; } @Override protected final boolean fetch() { - if (this.results != null && this.fetchMapped()) { + if (this.batchIterator != null && this.fetchFromBatch()) { return true; } while (this.originIterator.hasNext()) { T next = this.originIterator.next(); - assert this.results == null; - this.results = this.mapperCallback.apply(next); - if (this.results != null && this.fetchMapped()) { + assert this.batchIterator == null; + // Do fetch + this.batchIterator = this.mapperCallback.apply(next); + if (this.batchIterator != null && this.fetchFromBatch()) { return true; } } return false; } - protected boolean fetchMapped() { - E.checkNotNull(this.results, "mapper results"); - while (this.results.hasNext()) { - R result = this.results.next(); + protected boolean fetchFromBatch() { + E.checkNotNull(this.batchIterator, "mapper results"); + while (this.batchIterator.hasNext()) { + R result = this.batchIterator.next(); if (result != null) { assert this.current == none(); this.current = result; return true; } } - this.results = null; + this.resetBatchIterator(); return false; } + + protected final void resetBatchIterator() { + if (this.batchIterator == null) { + return; + } + close(this.batchIterator); + this.batchIterator = null; + } } diff --git a/src/main/java/com/baidu/hugegraph/iterator/ListIterator.java b/src/main/java/com/baidu/hugegraph/iterator/ListIterator.java new file mode 100644 index 0000000000..f21a436461 --- /dev/null +++ b/src/main/java/com/baidu/hugegraph/iterator/ListIterator.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.baidu.hugegraph.iterator; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import com.baidu.hugegraph.util.InsertionOrderUtil; + +public class ListIterator extends WrappedIterator { + + private final Iterator originIterator; + private final Iterator resultsIterator; + private final Collection results; + + public ListIterator(long capacity, Iterator origin) { + List results = InsertionOrderUtil.newList(); + while (origin.hasNext()) { + if (capacity >= 0L && results.size() >= capacity) { + throw new IllegalArgumentException( + "The iterator exceeded capacity " + capacity); + } + results.add(origin.next()); + } + this.originIterator = origin; + this.results = Collections.unmodifiableList(results); + this.resultsIterator = this.results.iterator(); + } + + public ListIterator(Collection origin) { + this.originIterator = origin.iterator(); + this.results = origin instanceof List ? + Collections.unmodifiableList((List) origin) : + Collections.unmodifiableCollection(origin); + this.resultsIterator = this.results.iterator(); + } + + @Override + public void remove() { + this.resultsIterator.remove(); + } + + public Collection list() { + return this.results; + } + + @Override + protected boolean fetch() { + assert this.current == none(); + if (!this.resultsIterator.hasNext()) { + return false; + } + this.current = this.resultsIterator.next(); + return true; + } + + @Override + protected Iterator originIterator() { + return this.originIterator; + } +} diff --git a/src/main/java/com/baidu/hugegraph/iterator/MapperIterator.java b/src/main/java/com/baidu/hugegraph/iterator/MapperIterator.java index f9930f5128..c02d17c27b 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/MapperIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/MapperIterator.java @@ -33,7 +33,7 @@ public MapperIterator(Iterator origin, Function mapper) { } @Override - protected Iterator originIterator() { + protected Iterator originIterator() { return this.originIterator; } diff --git a/src/main/java/com/baidu/hugegraph/iterator/WrappedIterator.java b/src/main/java/com/baidu/hugegraph/iterator/WrappedIterator.java index 30cf0725e2..c6e9ae7bc5 100644 --- a/src/main/java/com/baidu/hugegraph/iterator/WrappedIterator.java +++ b/src/main/java/com/baidu/hugegraph/iterator/WrappedIterator.java @@ -22,8 +22,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; -public abstract class WrappedIterator - implements Iterator, AutoCloseable, Metadatable { +public abstract class WrappedIterator implements CIter { private static final Object NONE = new Object(); @@ -86,6 +85,16 @@ protected static final R none() { return (R) NONE; } + public static void close(Iterator iterator) { + if (iterator instanceof AutoCloseable) { + try { + ((AutoCloseable) iterator).close(); + } catch (Exception e) { + throw new IllegalStateException("Failed to close iterator"); + } + } + } + protected abstract Iterator originIterator(); protected abstract boolean fetch(); diff --git a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java index 5bfcbcb53c..5c4ed4b68a 100644 --- a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java +++ b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java @@ -27,5 +27,5 @@ public class CommonVersion { // The second parameter of Version.of() is for all-in-one JAR public static final Version VERSION = Version.of(CommonVersion.class, - "1.7.1"); + "1.7.2"); } diff --git a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java index 4d292d6267..dc90b35bf2 100644 --- a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java +++ b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java @@ -30,10 +30,12 @@ import com.baidu.hugegraph.unit.config.OptionSpaceTest; import com.baidu.hugegraph.unit.date.SafeDateFormatTest; import com.baidu.hugegraph.unit.event.EventHubTest; +import com.baidu.hugegraph.unit.iterator.BatchMapperIteratorTest; import com.baidu.hugegraph.unit.iterator.ExtendableIteratorTest; import com.baidu.hugegraph.unit.iterator.FilterIteratorTest; import com.baidu.hugegraph.unit.iterator.FlatMapperFilterIteratorTest; import com.baidu.hugegraph.unit.iterator.FlatMapperIteratorTest; +import com.baidu.hugegraph.unit.iterator.ListIteratorTest; import com.baidu.hugegraph.unit.iterator.MapperIteratorTest; import com.baidu.hugegraph.unit.license.ExtraParamTest; import com.baidu.hugegraph.unit.license.LicenseCreateParamTest; @@ -74,6 +76,8 @@ MapperIteratorTest.class, FlatMapperIteratorTest.class, FlatMapperFilterIteratorTest.class, + ListIteratorTest.class, + BatchMapperIteratorTest.class, BytesTest.class, CollectionUtilTest.class, diff --git a/src/test/java/com/baidu/hugegraph/unit/iterator/BatchMapperIteratorTest.java b/src/test/java/com/baidu/hugegraph/unit/iterator/BatchMapperIteratorTest.java new file mode 100644 index 0000000000..e08ff69216 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/iterator/BatchMapperIteratorTest.java @@ -0,0 +1,265 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.baidu.hugegraph.unit.iterator; + +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.Test; + +import com.baidu.hugegraph.iterator.BatchMapperIterator; +import com.baidu.hugegraph.testutil.Assert; +import com.baidu.hugegraph.unit.BaseUnitTest; +import com.baidu.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor; +import com.google.common.collect.ImmutableList; + +@SuppressWarnings("resource") +public class BatchMapperIteratorTest extends BaseUnitTest { + + private static final Iterator EMPTY = Collections.emptyIterator(); + + private static final List DATA1 = ImmutableList.of(1); + private static final List DATA2 = ImmutableList.of(2, 3); + private static final List DATA3 = ImmutableList.of(4, 5, 6); + + private static final Function, Iterator> MAPPER = + batch -> batch.iterator(); + + @Test + public void testBatchMapper() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(1), ImmutableList.copyOf(results)); + + results = new BatchMapperIterator<>(1, DATA2.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(2, 3), + ImmutableList.copyOf(results)); + + results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(4, 5, 6), + ImmutableList.copyOf(results)); + } + + @Test + public void testBatch() { + Iterator results; + + results = new BatchMapperIterator<>(2, DATA2.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(2, 3), + ImmutableList.copyOf(results)); + + results = new BatchMapperIterator<>(2, DATA3.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(4, 5, 6), + ImmutableList.copyOf(results)); + + results = new BatchMapperIterator<>(3, DATA3.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(4, 5, 6), + ImmutableList.copyOf(results)); + + results = new BatchMapperIterator<>(4, DATA3.iterator(), MAPPER); + Assert.assertEquals(ImmutableList.of(4, 5, 6), + ImmutableList.copyOf(results)); + } + + @Test + public void testInvalidBatch() { + Assert.assertThrows(IllegalArgumentException.class, () -> { + new BatchMapperIterator<>(0, DATA1.iterator(), MAPPER); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + new BatchMapperIterator<>(-1, DATA1.iterator(), MAPPER); + }); + } + + @Test + public void testHasNext() { + Iterator results; + + results = new BatchMapperIterator<>(1, EMPTY, MAPPER); + Assert.assertFalse(results.hasNext()); + + results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER); + Assert.assertTrue(results.hasNext()); + } + + @Test + public void testHasNextAndNextWithMultiTimes() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER); + + for (int i = 0; i < 5; i++) { + Assert.assertTrue(results.hasNext()); + } + + for (int i = 0; i < 3; i++) { + results.next(); + } + + Assert.assertFalse(results.hasNext()); + Assert.assertFalse(results.hasNext()); + + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testNext() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER); + // Call next() without hasNext() + Assert.assertEquals(1, results.next()); + + results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + + results = new BatchMapperIterator<>(2, DATA3.iterator(), MAPPER); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + } + + @Test + public void testNextWithMultiTimes() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA2.iterator(), MAPPER); + + for (int i = 0; i < 2; i++) { + results.next(); + } + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testMapperWithBatch() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> { + Assert.assertEquals(1, batch.size()); + return batch.iterator(); + }); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + Assert.assertFalse(results.hasNext()); + + results = new BatchMapperIterator<>(2, DATA3.iterator(), batch -> { + if (batch.size() == 1) { + Assert.assertEquals(6, batch.get(0)); + } else { + Assert.assertEquals(2, batch.size()); + } + return batch.iterator(); + }); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + Assert.assertFalse(results.hasNext()); + + results = new BatchMapperIterator<>(3, DATA3.iterator(), batch -> { + Assert.assertEquals(3, batch.size()); + return batch.iterator(); + }); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + Assert.assertFalse(results.hasNext()); + + results = new BatchMapperIterator<>(4, DATA3.iterator(), batch -> { + Assert.assertEquals(3, batch.size()); + return batch.iterator(); + }); + Assert.assertEquals(4, results.next()); + Assert.assertEquals(5, results.next()); + Assert.assertEquals(6, results.next()); + Assert.assertFalse(results.hasNext()); + } + + @Test + public void testMapperThenReturn2X() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> { + List list = new ArrayList<>(); + for (int i : batch) { + list.add(2 * i); + } + return list.iterator(); + }); + + Assert.assertEquals(8, results.next()); + Assert.assertEquals(10, results.next()); + Assert.assertEquals(12, results.next()); + Assert.assertFalse(results.hasNext()); + } + + @Test + public void testMapperReturnNullThenHasNext() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> { + return null; + }); + Assert.assertFalse(results.hasNext()); + Assert.assertFalse(results.hasNext()); + } + + @Test + public void testMapperReturnNullThenNext() { + Iterator results; + + results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> { + return null; + }); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testClose() throws Exception { + CloseableItor vals = new CloseableItor<>(DATA1.iterator()); + + Iterator results = new BatchMapperIterator<>(1, vals, MAPPER); + + Assert.assertFalse(vals.closed()); + ((BatchMapperIterator) results).close(); + Assert.assertTrue(vals.closed()); + } +} diff --git a/src/test/java/com/baidu/hugegraph/unit/iterator/ExtendableIteratorTest.java b/src/test/java/com/baidu/hugegraph/unit/iterator/ExtendableIteratorTest.java index 1a9a635b5f..4c7ba31b82 100644 --- a/src/test/java/com/baidu/hugegraph/unit/iterator/ExtendableIteratorTest.java +++ b/src/test/java/com/baidu/hugegraph/unit/iterator/ExtendableIteratorTest.java @@ -175,7 +175,30 @@ public void testClose() throws Exception { } @Test - public void testCloseAfterNext() throws Exception { + public void testCloseAfterNext1() throws Exception { + CloseableItor c1 = new CloseableItor<>(DATA1.iterator()); + CloseableItor c2 = new CloseableItor<>(DATA2.iterator()); + CloseableItor c3 = new CloseableItor<>(DATA3.iterator()); + + ExtendableIterator results = new ExtendableIterator<>(); + results.extend(c1).extend(c2).extend(c3); + + results.next(); + results.hasNext(); + + Assert.assertTrue(c1.closed()); // close after iterated + Assert.assertFalse(c2.closed()); + Assert.assertFalse(c3.closed()); + + results.close(); + + Assert.assertTrue(c1.closed()); + Assert.assertTrue(c2.closed()); + Assert.assertTrue(c3.closed()); + } + + @Test + public void testCloseAfterNext3() throws Exception { CloseableItor c1 = new CloseableItor<>(DATA1.iterator()); CloseableItor c2 = new CloseableItor<>(DATA2.iterator()); CloseableItor c3 = new CloseableItor<>(DATA3.iterator()); @@ -191,8 +214,8 @@ public void testCloseAfterNext() throws Exception { results.next(); } - Assert.assertFalse(c1.closed()); - Assert.assertFalse(c2.closed()); + Assert.assertTrue(c1.closed()); + Assert.assertTrue(c2.closed()); Assert.assertFalse(c3.closed()); results.close(); diff --git a/src/test/java/com/baidu/hugegraph/unit/iterator/ListIteratorTest.java b/src/test/java/com/baidu/hugegraph/unit/iterator/ListIteratorTest.java new file mode 100644 index 0000000000..8ddd995ba0 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/iterator/ListIteratorTest.java @@ -0,0 +1,262 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.baidu.hugegraph.unit.iterator; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.junit.Test; + +import com.baidu.hugegraph.iterator.ListIterator; +import com.baidu.hugegraph.testutil.Assert; +import com.baidu.hugegraph.unit.BaseUnitTest; +import com.baidu.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; + +@SuppressWarnings("resource") +public class ListIteratorTest extends BaseUnitTest { + + private static final Iterator EMPTY = Collections.emptyIterator(); + + private static final List DATA1 = ImmutableList.of(1); + private static final List DATA2 = ImmutableList.of(2, 3); + private static final List DATA3 = ImmutableList.of(4, 5, 6); + + @Test + public void testCapacity() { + Iterator results; + + results = new ListIterator<>(0, EMPTY); + Assert.assertFalse(results.hasNext()); + Assert.assertEquals(0, Iterators.size(results)); + + results = new ListIterator<>(2, DATA1.iterator()); + Assert.assertTrue(results.hasNext()); + Assert.assertEquals(1, Iterators.size(results)); + + results = new ListIterator<>(2, DATA2.iterator()); + Assert.assertTrue(results.hasNext()); + Assert.assertEquals(2, Iterators.size(results)); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + new ListIterator<>(0, DATA1.iterator()); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + new ListIterator<>(2, DATA3.iterator()); + }); + } + + @Test + public void testList() { + ListIterator results; + + results = new ListIterator<>(-1, EMPTY); + Assert.assertEquals(ImmutableList.of(), results.list()); + + results = new ListIterator<>(-1, DATA1.iterator()); + Assert.assertEquals(ImmutableList.of(1), results.list()); + + results = new ListIterator<>(-1, DATA2.iterator()); + Assert.assertEquals(ImmutableList.of(2, 3), results.list()); + + results = new ListIterator<>(-1, DATA3.iterator()); + Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list()); + } + + @Test + public void testHasNext() { + Iterator origin = DATA1.iterator(); + Assert.assertTrue(origin.hasNext()); + + Iterator results = new ListIterator<>(-1, origin); + Assert.assertTrue(results.hasNext()); + Assert.assertTrue(results.hasNext()); + Assert.assertFalse(origin.hasNext()); + } + + @Test + public void testNext() { + Iterator results = new ListIterator<>(-1, DATA1.iterator()); + Assert.assertEquals(1, (int) results.next()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testNextAfterList() { + Iterator results = new ListIterator<>(-1, DATA1.iterator()); + Assert.assertEquals(ImmutableList.of(1), + ((ListIterator) results).list()); + Assert.assertEquals(1, (int) results.next()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testNextWithMultiTimes() { + Iterator results = new ListIterator<>(-1, DATA2.iterator()); + Assert.assertEquals(2, (int) results.next()); + Assert.assertEquals(3, (int) results.next()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testHasNextAndNext() { + Iterator results = new ListIterator<>(-1, DATA1.iterator()); + Assert.assertTrue(results.hasNext()); + Assert.assertTrue(results.hasNext()); + Assert.assertEquals(1, (int) results.next()); + Assert.assertFalse(results.hasNext()); + Assert.assertFalse(results.hasNext()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results.next(); + }); + } + + @Test + public void testRemove() { + List list = new ArrayList<>(DATA3); + ListIterator results = new ListIterator<>(-1, list.iterator()); + + Assert.assertEquals(ImmutableList.of(4, 5, 6), list); + Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list()); + + Assert.assertThrows(UnsupportedOperationException.class, () -> { + results.remove(); + }); + results.next(); + Assert.assertThrows(UnsupportedOperationException.class, () -> { + results.remove(); + }); + + Assert.assertEquals(ImmutableList.of(4, 5, 6), list); + Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list()); + } + + @Test + public void testRemoveWithoutResult() { + Iterator results = new ListIterator<>(-1, EMPTY); + Assert.assertThrows(UnsupportedOperationException.class, () -> { + results.remove(); + }); + + List list0 = new ArrayList<>(); + Iterator results2 = new ListIterator<>(-1, list0.iterator()); + Assert.assertThrows(UnsupportedOperationException.class, () -> { + results2.remove(); + }); + } + + @Test + public void testClose() throws Exception { + CloseableItor c1 = new CloseableItor<>(DATA1.iterator()); + + ListIterator results = new ListIterator<>(-1, c1); + + Assert.assertFalse(c1.closed()); + + results.close(); + + Assert.assertTrue(c1.closed()); + } + + @Test + public void testListWithConstructFromList() { + ListIterator results; + + results = new ListIterator<>(ImmutableList.of()); + Assert.assertEquals(ImmutableList.of(), results.list()); + + results = new ListIterator<>(DATA1); + Assert.assertEquals(ImmutableList.of(1), results.list()); + + results = new ListIterator<>(DATA2); + Assert.assertEquals(ImmutableList.of(2, 3), results.list()); + + results = new ListIterator<>(DATA3); + Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list()); + } + + @Test + public void testHasNextAndNextWithConstructFromList() { + ListIterator results0 = new ListIterator<>(ImmutableList.of()); + Assert.assertFalse(results0.hasNext()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results0.next(); + }); + + ListIterator results1 = new ListIterator<>(DATA1); + Assert.assertTrue(results1.hasNext()); + Assert.assertEquals(1, results1.next()); + Assert.assertFalse(results1.hasNext()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results1.next(); + }); + + ListIterator results3 = new ListIterator<>(DATA3); + Assert.assertTrue(results3.hasNext()); + Assert.assertEquals(4, results3.next()); + Assert.assertTrue(results3.hasNext()); + Assert.assertEquals(5, results3.next()); + Assert.assertTrue(results3.hasNext()); + Assert.assertEquals(6, results3.next()); + Assert.assertFalse(results3.hasNext()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results3.next(); + }); + } + + @Test + public void testNextWithConstructFromList() { + ListIterator results0 = new ListIterator<>(ImmutableList.of()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results0.next(); + }); + + ListIterator results3 = new ListIterator<>(DATA3); + Assert.assertEquals(4, results3.next()); + Assert.assertEquals(5, results3.next()); + Assert.assertEquals(6, results3.next()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results3.next(); + }); + } + + @Test + public void testNextAfterListWithConstructFromList() { + ListIterator results3 = new ListIterator<>(DATA3); + Assert.assertEquals(ImmutableList.of(4, 5, 6), results3.list()); + Assert.assertEquals(4, results3.next()); + Assert.assertEquals(5, results3.next()); + Assert.assertEquals(6, results3.next()); + Assert.assertThrows(NoSuchElementException.class, () -> { + results3.next(); + }); + } +}