package org.jgroups.tests.byteman;
import org.jboss.byteman.contrib.bmunit.BMNGRunner;
import org.jboss.byteman.contrib.bmunit.BMScript;
import org.jgroups.Global;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;
import org.jgroups.protocols.PING;
import org.jgroups.protocols.SHARED_LOOPBACK;
import org.jgroups.protocols.UNICAST2;
import org.jgroups.protocols.pbcast.GMS;
import org.jgroups.protocols.pbcast.NAKACK2;
import org.jgroups.util.Util;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
/**
* Tests the behavior of queueing messages (in NAKACK{2}) before becoming a server
* (https://issues.jboss.org/browse/JGRP-1522)
* @author Bela Ban
* @since 3.2
*/
@Test(groups=Global.BYTEMAN,sequential=true)
public class BecomeServerTest extends BMNGRunner {
JChannel a, b;
@AfterMethod
protected void cleanup() {
Util.close(b,a);
}
/**
* When we flush the server queue and one or more of the delivered messages triggers a response (in the same thread),
* we need to make sure the channel is connected, or else the JOIN will fail as the exception happens on the same
* thread. Note that the suggested fix on JGRP-1522 will solve this. Issue: https://issues.jboss.org/browse/JGRP-1522
*/
@BMScript(dir="scripts/BecomeServerTest", value="testSendingOfMsgsOnUnconnectedChannel")
public void testSendingOfMsgsOnUnconnectedChannel() throws Exception {
a=createChannel("A");
a.setReceiver(new ReceiverAdapter() {
public void receive(Message msg) {
System.out.println("A: received message from " + msg.getSrc() + ": " + msg.getObject());
}
});
a.connect("BecomeServerTest");
new Thread("MsgSender-A") {
public void run() {
sendMessage(a, "hello from A"); // will be blocked by byteman rendezvous
}
}.start();
b=createChannel("B");
b.setReceiver(new ReceiverAdapter() {
public void receive(Message msg) {
System.out.println("B: received message from " + msg.getSrc() + ": " + msg.getObject());
if(msg.getSrc().equals(a.getAddress())) {
try {
b.send(null, "This message would trigger an exception if the channel was not yet connected");
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}
});
b.connect("BecomeServerTest");
Util.waitUntilAllChannelsHaveSameSize(20000, 1000, a,b);
System.out.println("\nA: " + a.getView() + "\nB: " + b.getView());
}
protected void sendMessage(JChannel ch, String message) {
try {
Message msg=new Message(null, message);
msg.setFlag(Message.Flag.OOB);
ch.send(msg);
}
catch(Exception e) {
e.printStackTrace(System.err);
}
}
protected JChannel createChannel(String name) throws Exception {
JChannel ch=Util.createChannel(new SHARED_LOOPBACK().setValue("enable_bundling", false)
.setValue("enable_unicast_bundling", false),
new PING().setValue("timeout", 500).setValue("num_initial_members", 2),
new NAKACK2().setValue("become_server_queue_size", 10),
new UNICAST2(),
new GMS().setValue("print_local_addr", false));
ch.setName(name);
return ch;
}
}