package piePlateITs;
import java.security.Security;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import junit.framework.Assert;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jgroups.JChannel;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.pieShare.pieTools.piePlate.model.PiePlateBeanNames;
import org.pieShare.pieTools.piePlate.model.serializer.jacksonSerializer.JGroupsPieAddress;
import org.pieShare.pieTools.piePlate.service.channel.PlainTextChannel;
import org.pieShare.pieTools.piePlate.service.channel.api.ITwoWayChannel;
import org.pieShare.pieTools.piePlate.service.cluster.api.IClusterService;
import org.pieShare.pieTools.piePlate.service.cluster.exception.ClusterServiceException;
import org.pieShare.pieTools.piePlate.service.cluster.jgroupsCluster.JGroupsClusterService;
import org.pieShare.pieTools.piePlate.service.cluster.jgroupsCluster.ObjectBasedReceiver;
import org.pieShare.pieTools.piePlate.service.serializer.jacksonSerializer.JacksonSerializerService;
import org.pieShare.pieTools.piePlate.task.ChannelTask;
import org.pieShare.pieTools.pieUtilities.model.EncryptedPassword;
import org.pieShare.pieTools.pieUtilities.service.beanService.IBeanService;
import org.pieShare.pieTools.pieUtilities.service.pieExecutorService.api.IExecutorService;
import piePlateITs.helper.ClusterServiceTestHelper;
import piePlateITs.helper.TestMessage;
public class ClusterServiceIT {
private JGroupsClusterService service1;
private JGroupsClusterService service2;
private JGroupsClusterService service3;
private IBeanService beanService;
private IExecutorService executor1;
private IExecutorService executor2;
private IExecutorService executor3;
private JChannel channel1;
private JChannel channel2;
private JChannel channel3;
private EncryptedPassword pwd;
private String testChannelId;
@Before
public void before() throws Exception {
JacksonSerializerService serializer = new JacksonSerializerService();
this.beanService = Mockito.mock(IBeanService.class);
this.executor1 = Mockito.mock(IExecutorService.class);
this.executor2 = Mockito.mock(IExecutorService.class);
this.executor3 = Mockito.mock(IExecutorService.class);
ObjectBasedReceiver rec1 = new ObjectBasedReceiver();
rec1.setBeanService(beanService);
rec1.setExecutorService(executor1);
ObjectBasedReceiver rec2 = new ObjectBasedReceiver();
rec2.setBeanService(beanService);
rec2.setExecutorService(executor2);
ObjectBasedReceiver rec3 = new ObjectBasedReceiver();
rec3.setBeanService(beanService);
rec3.setExecutorService(executor3);
this.testChannelId = "testChannel";
PlainTextChannel channel = new PlainTextChannel();
channel.setChannelId(this.testChannelId);
channel.setSerializerService(serializer);
channel1 = new JChannel();
channel2 = new JChannel();
channel3 = new JChannel();
this.service1 = new JGroupsClusterService();
this.service1.setReceiver(rec1);
this.service1.setChannel(channel1);
this.service1.registerIncomingChannel(channel);
this.service1.registerOutgoingChannel(channel);
this.service2 = new JGroupsClusterService();
this.service2.setReceiver(rec2);
this.service2.setChannel(channel2);
this.service2.registerIncomingChannel(channel);
this.service2.registerOutgoingChannel(channel);
this.service3 = new JGroupsClusterService();
this.service3.setReceiver(rec3);
this.service3.setChannel(channel3);
this.service3.registerIncomingChannel(channel);
this.service3.registerOutgoingChannel(channel);
BouncyCastleProvider prov = new BouncyCastleProvider();
Security.addProvider(prov);
pwd = new EncryptedPassword();
PBEKeySpec keySpec = new PBEKeySpec("test".toCharArray());
pwd.setSecretKey(SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC", prov.getName()).generateSecret(keySpec));
pwd.setPassword("test".getBytes());
}
@Test(timeout = 50000)
public void testSimpleClustering() throws Exception {
String clusterName = "myTestCluster";
ClusterServiceTestHelper tester1 = prepareSimpleConnectionHelper(service1, clusterName);
ClusterServiceTestHelper tester2 = prepareSimpleConnectionHelper(service2, clusterName);
ClusterServiceTestHelper tester3 = prepareSimpleConnectionHelper(service3, clusterName);
startTester(tester1, false);
startTester(tester2, false);
startTester(tester3, false);
waitUntilDone(tester1);
waitUntilDone(tester2);
waitUntilDone(tester3);
Assert.assertEquals(3, service1.getMembersCount());
Assert.assertEquals(3, service2.getMembersCount());
Assert.assertEquals(3, service3.getMembersCount());
}
//@Test(timeout = 50000)
public void testSendingMessageToMany() throws Exception {
final TestMessage msg = new TestMessage();
msg.setType(TestMessage.class.getName());
msg.setMsg("This is a msg!");
msg.setAddress(new JGroupsPieAddress());
msg.getAddress().setChannelId(this.testChannelId);
Mockito.when(this.beanService.getBean(PiePlateBeanNames.getJgroupsPieAddress())).thenReturn(new JGroupsPieAddress());
ClusterServiceTestHelper tester1 = new ClusterServiceTestHelper(this.service1) {
@Override
public void run() {
try {
this.getService().connect("myTestCluster2");
this.getService().sendMessage(msg);
this.setDone(true);
} catch (ClusterServiceException e) {
e.printStackTrace();
}
}
};
final ClusterServiceTestHelper tester2 = prepareSimpleConnectionHelper(this.service2, "myTestCluster2");
final ClusterServiceTestHelper tester3 = prepareSimpleConnectionHelper(this.service3, "myTestCluster2");
prepareMessageCheckOnMock(tester2, executor2, msg);
prepareMessageCheckOnMock(tester3, executor3, msg);
startTester(tester2, true);
Assert.assertEquals(1, tester2.getService().getMembersCount());
startTester(tester3, true);
Assert.assertEquals(2, tester3.getService().getMembersCount());
new Thread(tester1).start();
waitUntilDone(tester1);
Assert.assertEquals(3, tester2.getService().getMembersCount());
waitUntilDone(tester2);
waitUntilDone(tester3);
}
//@Test(timeout = 50000)
public void testSendingMessageToSingle() throws Exception {
final String clusterName = "myTestCluster3";
final TestMessage msg = new TestMessage();
msg.setType(TestMessage.class.getName());
msg.setMsg("This is a msg!");
JGroupsPieAddress add = new JGroupsPieAddress();
add.setChannelId(this.testChannelId);
add.setClusterName(clusterName);
msg.setAddress(add);
ChannelTask task = new ChannelTask();
task.setExecutorService(this.executor1);
//Mockito.when(this.beanService.getBean(PiePlateBeanNames.())).thenReturn();
Mockito.when(this.beanService.getBean(PiePlateBeanNames.getJgroupsPieAddress())).thenReturn(add);
ClusterServiceTestHelper tester1 = new ClusterServiceTestHelper(this.service1) {
@Override
public void run() {
try {
this.getService().connect(clusterName);
this.getService().sendMessage(msg);
this.setDone(true);
} catch (ClusterServiceException e) {
e.printStackTrace();
}
}
};
final ClusterServiceTestHelper tester2 = prepareSimpleConnectionHelper(this.service2, clusterName);
final ClusterServiceTestHelper tester3 = prepareSimpleConnectionHelper(this.service3, clusterName);
prepareMessageCheckOnMock(tester2, executor2, msg);
startTester(tester2, true);
startTester(tester3, false);
JGroupsPieAddress ad = new JGroupsPieAddress();
ad.setAddress(this.channel2.getAddress());
msg.setAddress(ad);
startTester(tester1, false);
waitUntilDone(tester2);
Mockito.verify(this.executor3, Mockito.times(0)).handlePieEvent(Mockito.any(TestMessage.class));
}
//@Test(timeout = 50000)
public void testSendingManyMessagesToSingle() throws Exception {
final String clusterName = "myTestCluster4";
final TestMessage msg = new TestMessage();
msg.setType(TestMessage.class.getName());
msg.getAddress().setChannelId(this.testChannelId);
final String value = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
Integer expectedCountPerLetter = 2;
final char[] values = value.toCharArray();
Mockito.when(this.beanService.getBean(PiePlateBeanNames.getJgroupsPieAddress())).thenReturn(new JGroupsPieAddress());
ClusterServiceTestHelper tester1 = new ClusterServiceTestHelper(this.service1) {
@Override
public void run() {
try {
this.getService().connect(clusterName);
for (int i = 0; i < values.length; i++) {
msg.setMsg(String.valueOf(values[i]));
this.getService().sendMessage(msg);
}
this.setDone(true);
} catch (ClusterServiceException e) {
e.printStackTrace();
}
}
};
final ClusterServiceTestHelper tester2 = prepareSimpleConnectionHelper(service2, clusterName);
startTester(tester2, true);
final Map<String, Integer> rec = new HashMap<String, Integer>();
Mockito.doAnswer(new Answer() {
private int numRec = 0;
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
TestMessage targetMsg = (TestMessage) invocation.getArguments()[0];
//System.out.println(targetMsg.getMsg());
Integer num = 1;
numRec++;
if (rec.containsKey(targetMsg.getMsg())) {
num = rec.get(targetMsg.getMsg()) + 1;
}
rec.put(targetMsg.getMsg(), num);
if (numRec == values.length) {
tester2.setDone(true);
}
return null;
}
}).when(this.executor2).handlePieEvent(Mockito.<TestMessage>any());
JGroupsPieAddress ad = new JGroupsPieAddress();
ad.setAddress(this.channel2.getAddress());
msg.setAddress(ad);
startTester(tester1, false);
waitUntilDone(tester2);
for (int i = 0; i < values.length; i++) {
String key = String.valueOf(values[i]);
Assert.assertTrue("Failed on letter: " + values[i], rec.containsKey(key));
Assert.assertEquals(expectedCountPerLetter, rec.get(key));
}
}
private void startTester(ClusterServiceTestHelper tester, boolean resetDone) throws Exception {
new Thread(tester).start();
waitUntilDone(tester);
if (resetDone) {
tester.setDone(false);
}
}
private ClusterServiceTestHelper prepareSimpleConnectionHelper(IClusterService service, final String clusterName) {
ClusterServiceTestHelper tester = new ClusterServiceTestHelper(service) {
@Override
public void run() {
try {
this.getService().connect(clusterName);
this.setDone(true);
} catch (ClusterServiceException e) {
e.printStackTrace();
}
}
};
return tester;
}
private void prepareMessageCheckOnMock(final ClusterServiceTestHelper tester, IExecutorService mock, final TestMessage expected) throws Exception {
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
TestMessage targetMsg = (TestMessage) invocation.getArguments()[0];
Assert.assertEquals(expected.getMsg(), targetMsg.getMsg());
tester.setDone(true);
return null;
}
}).when(mock).handlePieEvent(Mockito.<TestMessage>any());
}
private void waitUntilDone(ClusterServiceTestHelper testee) throws InterruptedException {
while (!testee.getDone()) {
Thread.sleep(500);
}
}
}