/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. 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.client;
import com.hazelcast.client.ClientProperties.ClientPropertyName;
import com.hazelcast.config.Config;
import com.hazelcast.config.GroupConfig;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.NearCacheConfig;
import com.hazelcast.core.*;
import com.hazelcast.core.LifecycleEvent.LifecycleState;
import com.hazelcast.impl.GroupProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import static com.hazelcast.client.TestUtility.newHazelcastClient;
import static com.hazelcast.impl.TestUtil.OrderKey;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.fail;
@RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class)
public class HazelcastClientClusterTest {
@BeforeClass
public static void init() throws Exception {
System.setProperty(GroupProperties.PROP_WAIT_SECONDS_BEFORE_JOIN, "1");
System.setProperty(GroupProperties.PROP_VERSION_CHECK_ENABLED, "false");
Hazelcast.shutdownAll();
}
@After
@Before
public void cleanup() throws Exception {
HazelcastClient.shutdownAll();
Hazelcast.shutdownAll();
}
@Test
public void testLockOwnerClientDies() throws Exception {
final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
HazelcastClient client1 = newHazelcastClient(h1);
HazelcastClient client2 = newHazelcastClient(h1);
final IMap c1 = client1.getMap("default");
final IMap c2 = client2.getMap("default");
final IMap m1 = h1.getMap("default");
c1.lock("key");
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
c2.lock("key");
latch.countDown();
}
}).start();
Thread.sleep(1000); // make sure c1.lock("key") is called and blocked
client1.shutdown();
assertTrue(latch.await(10, TimeUnit.SECONDS));
}
@Test
public void testLockWaitingClientDies() throws Exception {
final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
HazelcastClient client1 = newHazelcastClient(h1);
HazelcastClient client2 = newHazelcastClient(h1);
final IMap c1 = client1.getMap("default");
final IMap c2 = client2.getMap("default");
final IMap m1 = h1.getMap("default");
m1.lock("key");
new Thread(new Runnable() {
public void run() {
c1.lock("key");
}
}).start();
Thread.sleep(1000); // make sure c1.lock("key") is called and blocked
client1.shutdown();
Thread.sleep(1000);
m1.unlock("key");
assertTrue(c2.tryLock("key"));
}
@Test
public void testAffinity() throws Exception {
final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config());
final HazelcastInstance h3 = Hazelcast.newHazelcastInstance(new Config());
final HazelcastInstance h4 = Hazelcast.newHazelcastInstance(new Config());
HazelcastClient client = newHazelcastClient(h2);
final IMap c1 = client.getMap("default");
final IMap m1 = h4.getMap("default");
int count = 1000;
OrderKey[] keys = new OrderKey[count];
for (int i = 0; i < count; i++) {
OrderKey key = new OrderKey(i, i % 119);
keys[i] = key;
m1.put(key, i);
}
for (OrderKey key : keys) {
Member member1 = h1.getPartitionService().getPartition(key).getOwner();
Member member2 = h1.getPartitionService().getPartition(key.getPartitionKey()).getOwner();
assertEquals(member1, member2);
assertEquals(key.getOrderId(), c1.get(key));
assertEquals(key.getOrderId(), m1.get(key));
}
}
@Test
public void testUseBackupDataGet() throws Exception {
final Config config = new Config();
final MapConfig mapConfig = new MapConfig();
mapConfig.setName("q");
mapConfig.setReadBackupData(true);
config.setMapConfigs(Collections.singletonMap(mapConfig.getName(), mapConfig));
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
h1.getMap("q").put("q", "Q");
Thread.sleep(50L);
HazelcastClient client = newHazelcastClient(h2);
assertEquals("Q", client.getMap("q").get("q"));
}
@Test
public void testNearCache() throws Exception {
final Config config = new Config();
NearCacheConfig nearCacheConfig = new NearCacheConfig();
nearCacheConfig.setMaxSize(1000);
config.getMapConfig("default").setNearCacheConfig(nearCacheConfig);
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
IMap m1 = h1.getMap("default");
m1.put("1", "value");
HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
IMap m2 = h2.getMap("default");
assertEquals("value", m2.get("1"));
assertEquals("value", m1.get("1"));
HazelcastClient client1 = newHazelcastClient(h1);
HazelcastClient client2 = newHazelcastClient(h2);
for (int i = 0; i < 10; i++) {
assertEquals("value", client1.getMap("default").get("1"));
assertEquals("value", client2.getMap("default").get("1"));
}
}
@Test
public void testMembershipListener() throws Exception {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
HazelcastClient client = newHazelcastClient(h1);
final CountDownLatch memberAddLatch = new CountDownLatch(1);
final CountDownLatch memberRemoveLatch = new CountDownLatch(1);
client.getCluster().addMembershipListener(new MembershipListener() {
public void memberAdded(MembershipEvent membershipEvent) {
memberAddLatch.countDown();
}
public void memberRemoved(MembershipEvent membershipEvent) {
memberRemoveLatch.countDown();
}
});
HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config());
h2.getLifecycleService().shutdown();
assertTrue(memberAddLatch.await(10, TimeUnit.SECONDS));
assertTrue(memberRemoveLatch.await(10, TimeUnit.SECONDS));
client.shutdown();
}
@Test(expected = IllegalStateException.class, timeout = 50000L)
public void testNoClusterOnStart() throws Exception {
final ClientProperties clientProperties =
ClientProperties.createBaseClientProperties(GroupConfig.DEFAULT_GROUP_NAME, GroupConfig.DEFAULT_GROUP_PASSWORD);
clientProperties.setPropertyValue(ClientPropertyName.INIT_CONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_TIMEOUT, "500");
TestUtility.newHazelcastClient(clientProperties, "localhost:5701");
}
@Test(expected = NoMemberAvailableException.class, timeout = 50000L)
public void testNoClusterAfterStart() throws Exception {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
final ClientProperties clientProperties =
ClientProperties.createBaseClientProperties(GroupConfig.DEFAULT_GROUP_NAME, GroupConfig.DEFAULT_GROUP_PASSWORD);
clientProperties.setPropertyValue(ClientPropertyName.INIT_CONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_TIMEOUT, "100");
HazelcastClient client = newHazelcastClient(clientProperties, h1);
final IMap<Object, Object> map = client.getMap("default");
map.put("smth", "nothing");
h1.getLifecycleService().shutdown();
map.put("smth", "nothing");
}
@Test(timeout = 120000L)
public void testRestartCluster() throws Exception {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
final ClientProperties clientProperties =
ClientProperties.createBaseClientProperties(GroupConfig.DEFAULT_GROUP_NAME, GroupConfig.DEFAULT_GROUP_PASSWORD);
clientProperties.setPropertyValue(ClientPropertyName.INIT_CONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_TIMEOUT, "500");
HazelcastClient client = newHazelcastClient(clientProperties, h1);
final IMap<String, String> map = client.getMap("default");
final List<String> values = new CopyOnWriteArrayList<String>();
map.addEntryListener(new EntryAdapter<String, String>() {
@Override
public void entryAdded(EntryEvent<String, String> event) {
values.add(event.getValue());
}
@Override
public void entryUpdated(EntryEvent<String, String> event) {
values.add(event.getValue());
}
}, true);
final BlockingQueue<LifecycleState> states = new LinkedBlockingQueue<LifecycleState>();
client.getLifecycleService().addLifecycleListener(new LifecycleListener() {
public void stateChanged(LifecycleEvent event) {
states.add(event.getState());
}
});
map.put("smth", "nothing1");
Thread.sleep(50L);
assertArrayEquals(values.toString(), new String[]{"nothing1"}, values.toArray(new String[0]));
h1.getLifecycleService().shutdown();
assertEquals(LifecycleState.CLIENT_CONNECTION_LOST, states.poll(500L, TimeUnit.MILLISECONDS));
Thread.sleep(50L);
try {
map.put("smth", "nothing2");
fail("nothing2");
} catch (NoMemberAvailableException e) {
}
try {
map.put("smth", "nothing3");
fail("nothing3");
} catch (NoMemberAvailableException e) {
}
h1 = Hazelcast.newHazelcastInstance(new Config());
assertEquals(LifecycleState.CLIENT_CONNECTION_OPENING, states.poll(500L, TimeUnit.MILLISECONDS));
assertEquals(LifecycleState.CLIENT_CONNECTION_OPENED, states.poll(30000L, TimeUnit.MILLISECONDS));
map.put("smth", "nothing4");
Thread.sleep(50L);
assertArrayEquals(values.toString(), new String[]{"nothing1", "nothing4"}, values.toArray(new String[0]));
}
@Test(timeout = 120000L)
public void testRestartClusterTwice() throws Exception {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
final ClientProperties clientProperties =
ClientProperties.createBaseClientProperties(GroupConfig.DEFAULT_GROUP_NAME, GroupConfig.DEFAULT_GROUP_PASSWORD);
clientProperties.setPropertyValue(ClientPropertyName.INIT_CONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_ATTEMPTS_LIMIT, "5");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_TIMEOUT, "1000");
HazelcastClient client = newHazelcastClient(clientProperties, h1);
final IMap<String, String> map = client.getMap("default");
final List<String> values = new ArrayList<String>();
map.addEntryListener(new EntryAdapter<String, String>() {
@Override
public void entryAdded(EntryEvent<String, String> event) {
values.add(event.getValue());
}
@Override
public void entryUpdated(EntryEvent<String, String> event) {
values.add(event.getValue());
}
}, true);
final BlockingQueue<LifecycleState> states = new LinkedBlockingQueue<LifecycleState>();
client.getLifecycleService().addLifecycleListener(new LifecycleListener() {
public void stateChanged(LifecycleEvent event) {
states.add(event.getState());
}
});
map.put("smth", "nothing");
for (int i = 0; i < 2; i++) {
h1.getLifecycleService().shutdown();
assertEquals(LifecycleState.CLIENT_CONNECTION_LOST, states.poll(500L, TimeUnit.MILLISECONDS));
try {
map.put("smth", "nothing-" + i);
fail();
} catch (NoMemberAvailableException e) {
}
Thread.sleep(50L);
try {
map.put("smth", "nothing_" + i);
fail();
} catch (NoMemberAvailableException e) {
}
Thread.sleep(50L);
h1 = Hazelcast.newHazelcastInstance(new Config());
assertEquals(LifecycleState.CLIENT_CONNECTION_OPENING, states.poll(500L, TimeUnit.MILLISECONDS));
assertEquals(LifecycleState.CLIENT_CONNECTION_OPENED, states.poll(1000L, TimeUnit.MILLISECONDS));
map.put("smth", "nothing" + i);
Thread.sleep(50L);
}
assertArrayEquals(values.toString(), new String[]{"nothing", "nothing0", "nothing1"}, values.toArray(new String[0]));
}
@Test(expected = NoMemberAvailableException.class)
public void testNoClusterAfterStartIssue328() throws Exception {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config());
final ClientProperties clientProperties =
ClientProperties.createBaseClientProperties(GroupConfig.DEFAULT_GROUP_NAME, GroupConfig.DEFAULT_GROUP_PASSWORD);
clientProperties.setPropertyValue(ClientPropertyName.INIT_CONNECTION_ATTEMPTS_LIMIT, "2");
clientProperties.setPropertyValue(ClientPropertyName.RECONNECTION_TIMEOUT, "500");
HazelcastClient client = newHazelcastClient(clientProperties, h1);
final IMap<Object, Object> map = client.getMap("default");
h1.getLifecycleService().shutdown();
map.put("smth", "nothing");
}
}