/* * 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; import com.hazelcast.config.Config; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.ReplicatedMap; import com.hazelcast.instance.HazelcastInstanceFactory; import com.hazelcast.test.AssertTask; import com.hazelcast.test.TestHazelcastInstanceFactory; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(Parameterized.class) public class ReplicatedMapWriteOrderTest extends ReplicatedMapAbstractTest { int nodeCount; int operations; int keyCount; public ReplicatedMapWriteOrderTest(int nodeCount, int operations, int keyCount) { this.nodeCount = nodeCount; this.operations = operations; this.keyCount = keyCount; } @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ {2, 50, 1}, {2, 50, 10}, {2, 50, 50}, // {3, 50, 1}, {3, 50, 10}, {3, 50, 50}, // {3, 10, 10}, {3, 50, 50}, {3, 100, 100}, // {3, 150, 150}, {3, 200, 200}, {3, 250, 250}, // {3, 300, 300}, {3, 500, 500}, {3, 750, 750}, // {3, 500, 1}, {3, 500, 10}, {3, 500, 100}, {3, 500, 500}, // {3, 1000, 1}, {3, 1000, 10}, {3, 1000, 100}, {3, 1000, 1000}, // {3, 2000, 1}, {3, 2000, 10}, {3, 2000, 100}, {3, 2000, 1000}, // {5, 500, 1}, {5, 500, 10}, {5, 500, 100}, {5, 500, 500}, // {5, 1000, 1}, {5, 1000, 10}, {5, 1000, 100}, {5, 1000, 1000}, // {10, 1000, 1}, {10, 1000, 10}, {10, 1000, 100}, {10, 1000, 1000}, // {15, 2000, 1}, {15, 2000, 10}, {15, 2000, 100}, {15, 2000, 1000}, // {20, 2000, 1}, {20, 2000, 10}, {20, 2000, 100}, {20, 2000, 1000}, // {20, 5000, 1}, {20, 5000, 10}, {20, 5000, 1000}, {20, 5000, 3000}, }); } @After public void setUp() throws Exception { HazelcastInstanceFactory.terminateAll(); } @Test public void testDataIntegrity() throws InterruptedException { System.out.println("nodeCount = " + nodeCount); System.out.println("operations = " + operations); System.out.println("keyCount = " + keyCount); Config config = new Config(); config.getReplicatedMapConfig("test").setReplicationDelayMillis(0); TestHazelcastInstanceFactory factory = new TestHazelcastInstanceFactory(nodeCount); final HazelcastInstance[] instances = factory.newInstances(config); String replicatedMapName = "test"; final List<ReplicatedMap> maps = createMapOnEachInstance(instances, replicatedMapName); ArrayList<Integer> keys = generateRandomIntegerList(keyCount); Thread[] threads = createThreads(nodeCount, maps, keys, operations); for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } for (int i = 0; i < keyCount; i++) { final String key = "foo-" + keys.get(i); assertTrueEventually(new AssertTask() { @Override public void run() throws Exception { System.out.println("---------------------"); System.out.println("key = " + key); printValues(); assertValuesAreEqual(); } private void printValues() throws Exception { for (int j = 0; j < maps.size(); j++) { ReplicatedMap map = maps.get(j); System.out.println("value[" + j + "] = " + map.get(key) + ", store version: " + getStore(map, key).getVersion()); } } private void assertValuesAreEqual() { for (int i = 0; i < maps.size() - 1; i++) { ReplicatedMap map1 = maps.get(i); ReplicatedMap map2 = maps.get(i + 1); Object v1 = map1.get(key); Object v2 = map2.get(key); assertNotNull(v1); assertNotNull(v2); assertEquals(v1, v2); } } }, 120); } } private Thread[] createThreads(int count, List<ReplicatedMap> maps, ArrayList<Integer> keys, int operations) { Thread[] threads = new Thread[count]; for (int i = 0; i < count; i++) { threads[i] = createPutOperationThread(maps.get(i), keys, operations); } return threads; } private Thread createPutOperationThread(final ReplicatedMap<String, Object> map, final ArrayList<Integer> keys, final int operations) { return new Thread(new Runnable() { @Override public void run() { Random random = new Random(); int size = keys.size(); for (int i = 0; i < operations; i++) { int index = i % size; String key = "foo-" + keys.get(index); map.put(key, random.nextLong()); boolean containsKey = map.containsKey(key); assert containsKey; } } }); } }