/*
* Copyright (c) 2008-2017, Hazelcast, Inc. 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.hazelcast.replicatedmap.impl.record;
import com.hazelcast.replicatedmap.merge.ReplicatedMapMergePolicy;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import com.hazelcast.util.scheduler.ScheduledEntry;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class LazyIteratorTest
extends HazelcastTestSupport {
private static final InternalReplicatedMapStorage<String, Integer> TEST_DATA_SIMPLE;
private static final InternalReplicatedMapStorage<String, Integer> TEST_DATA_TOMBS;
private static final ReplicatedRecordStore REPLICATED_RECORD_STORE = new NoOpReplicatedRecordStore();
static {
TEST_DATA_SIMPLE = new InternalReplicatedMapStorage<String, Integer>();
for (int i = 0; i < 100; i++) {
String key = "key-" + i;
TEST_DATA_SIMPLE.put(key, new ReplicatedRecord<String, Integer>(key, i, -1));
TEST_DATA_SIMPLE.incrementVersion();
}
TEST_DATA_TOMBS = new InternalReplicatedMapStorage<String, Integer>();
for (int i = 0; i < 100; i++) {
String key = "key-" + i;
Integer value = i % 2 == 0 ? i : null;
ReplicatedRecord<String, Integer> record = new ReplicatedRecord<String, Integer>(key, value, -1);
TEST_DATA_TOMBS.put(key, record);
TEST_DATA_TOMBS.incrementVersion();
}
}
@Test
public void test_lazy_set_size() throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> set = new LazySet<String, Integer, String>(factory, TEST_DATA_SIMPLE);
assertEquals(100, set.size());
}
@Test
public void test_lazy_set_empty() throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> set = new LazySet<String, Integer, String>(factory, TEST_DATA_SIMPLE);
assertFalse(set.isEmpty());
}
@Test
public void test_lazy_collection_size() throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_SIMPLE);
assertEquals(100, collection.size());
}
@Test
public void test_lazy_collection_empty() throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_SIMPLE);
assertFalse(collection.isEmpty());
}
@Test
public void test_lazy_values_no_tombs_with_has_next()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_SIMPLE);
Iterator<Integer> iterator = collection.iterator();
int count = 0;
Set<Integer> values = new HashSet<Integer>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next());
}
assertEquals(100, count);
assertEquals(100, values.size());
}
@Test
public void test_lazy_values_no_tombs_with_has_next_every_second_time()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_SIMPLE);
Iterator<Integer> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
iterator.hasNext();
}
values.add(iterator.next());
}
assertEquals(100, values.size());
}
@Test
public void test_lazy_values_no_tombs_more_elements_possible()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_SIMPLE);
Iterator<Integer> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
values.add(iterator.next());
}
assertEquals(100, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_values_with_tombs_with_has_next()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Iterator<Integer> iterator = collection.iterator();
int count = 0;
Set<Integer> values = new HashSet<Integer>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next());
}
assertEquals(50, count);
assertEquals(50, values.size());
}
@Test
public void test_lazy_values_with_tombs_with_next()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Iterator<Integer> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_values_with_tombs_copy()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Set<Integer> copy = new HashSet<Integer>(collection);
Iterator<Integer> iterator = copy.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_values_with_tombs_to_array_new_array()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Object[] array = collection.toArray();
assertEquals(50, array.length);
}
@Test
public void test_lazy_values_with_tombs_to_array_passed_array_too_small()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Integer[] array = collection.toArray(new Integer[0]);
assertEquals(50, array.length);
}
@Test
public void test_lazy_values_with_tombs_to_array_passed_array_matching_size()
throws Exception {
ValuesIteratorFactory<String, Integer> factory = new ValuesIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazyCollection<String, Integer> collection = new LazyCollection<String, Integer>(factory, TEST_DATA_TOMBS);
Integer[] array = collection.toArray(new Integer[50]);
assertEquals(50, array.length);
}
@Test
public void test_lazy_keyset_no_tombs_with_has_next()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_SIMPLE);
Iterator<String> iterator = collection.iterator();
int count = 0;
Set<String> values = new HashSet<String>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next());
}
assertEquals(100, count);
assertEquals(100, values.size());
}
@Test
public void test_lazy_keyset_no_tombs_with_has_next_every_second_time()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_SIMPLE);
Iterator<String> iterator = collection.iterator();
Set<String> values = new HashSet<String>();
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
iterator.hasNext();
}
values.add(iterator.next());
}
assertEquals(100, values.size());
}
@Test
public void test_lazy_keyset_no_tombs_more_elements_possible()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_SIMPLE);
Iterator<String> iterator = collection.iterator();
Set<String> values = new HashSet<String>();
for (int i = 0; i < 100; i++) {
values.add(iterator.next());
}
assertEquals(100, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_keyset_with_tombs_with_has_next()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
Iterator<String> iterator = collection.iterator();
int count = 0;
Set<String> values = new HashSet<String>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next());
}
assertEquals(50, count);
assertEquals(50, values.size());
}
@Test
public void test_lazy_keyset_with_tombs_with_next()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
Iterator<String> iterator = collection.iterator();
Set<String> values = new HashSet<String>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_keyset_with_tombs_copy()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
Set<String> copy = new HashSet<String>(collection);
Iterator<String> iterator = copy.iterator();
Set<String> values = new HashSet<String>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_keyset_with_tombs_to_array_new_array()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
Object[] array = collection.toArray();
assertEquals(50, array.length);
}
@Test
public void test_lazy_keyset_with_tombs_to_array_passed_array_too_small()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
String[] array = collection.toArray(new String[0]);
assertEquals(50, array.length);
}
@Test
public void test_lazy_keyset_with_tombs_to_array_passed_array_matching_size()
throws Exception {
KeySetIteratorFactory<String, Integer> factory = new KeySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, String> collection = new LazySet<String, Integer, String>(factory, TEST_DATA_TOMBS);
String[] array = collection.toArray(new String[50]);
assertEquals(50, array.length);
}
@Test
public void test_lazy_entryset_no_tombs_with_has_next()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_SIMPLE);
Iterator<Map.Entry<String, Integer>> iterator = collection.iterator();
int count = 0;
Set<Integer> values = new HashSet<Integer>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next().getValue());
}
assertEquals(100, count);
assertEquals(100, values.size());
}
@Test
public void test_lazy_entryset_no_tombs_with_has_next_every_second_time()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_SIMPLE);
Iterator<Map.Entry<String, Integer>> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
iterator.hasNext();
}
values.add(iterator.next().getValue());
}
assertEquals(100, values.size());
}
@Test
public void test_lazy_entryset_no_tombs_more_elements_possible()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_SIMPLE);
Iterator<Map.Entry<String, Integer>> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
values.add(iterator.next().getValue());
}
assertEquals(100, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_entryset_with_tombs_with_has_next()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Iterator<Map.Entry<String, Integer>> iterator = collection.iterator();
int count = 0;
Set<Integer> values = new HashSet<Integer>();
while (iterator.hasNext()) {
count++;
values.add(iterator.next().getValue());
}
assertEquals(50, count);
assertEquals(50, values.size());
}
@Test
public void test_lazy_entryset_with_tombs_with_next()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Iterator<Map.Entry<String, Integer>> iterator = collection.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next().getValue());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_entryset_with_tombs_copy()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Set<Map.Entry<String, Integer>> copy = new HashSet<Map.Entry<String, Integer>>(collection);
Iterator<Map.Entry<String, Integer>> iterator = copy.iterator();
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < 50; i++) {
values.add(iterator.next().getValue());
}
assertEquals(50, values.size());
try {
iterator.next();
fail("Shouldn't have further elements!");
} catch (NoSuchElementException e) {
// We need to catch it here since we won't have a successful test
// if any of the prior calls would throw it!
}
}
@Test
public void test_lazy_entryset_with_tombs_to_array_new_array()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Object[] array = collection.toArray();
assertEquals(50, array.length);
}
@Test
public void test_lazy_entryset_with_tombs_to_array_passed_array_too_small()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Map.Entry<String, Integer>[] array = collection.toArray(new Map.Entry[0]);
assertEquals(50, array.length);
}
@Test
public void test_lazy_entryset_with_tombs_to_array_passed_array_matching_size()
throws Exception {
EntrySetIteratorFactory<String, Integer> factory = new EntrySetIteratorFactory<String, Integer>(REPLICATED_RECORD_STORE);
LazySet<String, Integer, Map.Entry<String, Integer>> collection = //
new LazySet<String, Integer, Map.Entry<String, Integer>>(factory, TEST_DATA_TOMBS);
Map.Entry<String, Integer>[] array = collection.toArray(new Map.Entry[50]);
assertEquals(50, array.length);
}
private static class NoOpReplicatedRecordStore implements ReplicatedRecordStore {
@Override
public String getName() {
return null;
}
@Override
public Object remove(Object key) {
return null;
}
@Override
public Object removeWithVersion(Object key, long version) {
return null;
}
@Override
public void evict(Object key) {
}
@Override
public Object get(Object key) {
return null;
}
@Override
public Object put(Object key, Object value) {
return null;
}
@Override
public Object put(Object key, Object value, long ttl, TimeUnit timeUnit, boolean incrementHits) {
return null;
}
@Override
public Object putWithVersion(Object key, Object value, long ttl, TimeUnit timeUnit, boolean incrementHits, long version) {
return null;
}
@Override
public boolean containsKey(Object key) {
return false;
}
@Override
public boolean containsValue(Object value) {
return false;
}
@Override
public ReplicatedRecord getReplicatedRecord(Object key) {
return null;
}
@Override
public Set keySet(boolean lazy) {
return null;
}
@Override
public Collection values(boolean lazy) {
return null;
}
@Override
public Collection values(Comparator comparator) {
return null;
}
@Override
public Set entrySet(boolean lazy) {
return null;
}
@Override
public int size() {
return 0;
}
@Override
public void clear() {
}
@Override
public void clearWithVersion(long version) {
}
@Override
public void reset() {
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Object unmarshall(Object key) {
return key;
}
@Override
public Object marshall(Object key) {
return key;
}
@Override
public void destroy() {
}
@Override
public long getVersion() {
return 0;
}
@Override
public boolean isStale(long version) {
return false;
}
@Override
public Iterator<ReplicatedRecord> recordIterator() {
return null;
}
@Override
public void putRecords(Collection<RecordMigrationInfo> records, long version) {
}
@Override
public InternalReplicatedMapStorage getStorage() {
return null;
}
@Override
public ScheduledEntry<Object, Object> cancelTtlEntry(Object key) {
return null;
}
@Override
public boolean scheduleTtlEntry(long delayMillis, Object key, Object object) {
return false;
}
@Override
public boolean isLoaded() {
return false;
}
@Override
public void setLoaded(boolean loaded) {
}
@Override
public boolean merge(Object key, ReplicatedMapEntryView entryView, ReplicatedMapMergePolicy policy) {
return false;
}
}
}