package org.deephacks.westty.tests; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import org.deephacks.confit.admin.AdminContext; import org.deephacks.confit.jaxrs.AdminContextJaxrsProxy; import org.deephacks.westty.Westty; import org.deephacks.westty.config.ClusterConfig; import org.deephacks.westty.config.ProtobufConfig; import org.deephacks.westty.config.ServerConfig; import org.deephacks.westty.config.SockJsConfig; import org.deephacks.westty.protobuf.ProtobufClient; import org.deephacks.westty.protobuf.ProtobufSerializer; import org.deephacks.westty.spi.IoExecutors; import org.deephacks.westty.tests.ClusterMessages.AsyncPublishRequest; import org.deephacks.westty.tests.ClusterMessages.AsyncSendRequest; import org.deephacks.westty.tests.ClusterMessages.GetPublishRequest; import org.deephacks.westty.tests.ClusterMessages.GetPublishResponse; import org.deephacks.westty.tests.ClusterMessages.GetSendRequest; import org.deephacks.westty.tests.ClusterMessages.GetSendResponse; import org.slf4j.LoggerFactory; import javax.enterprise.inject.spi.BeanManager; import java.io.IOException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; /** * Tests that a cluster of instances can be setup programmatically on the * same machine without port conflicts. Do note that all servers will be * running in the same class loader, so the tests will try to verify that * servers are isolated from one another. * * TODO: These tests work, but shutdown of westty does not, so there will be port conflicts */ public class ClusterIntegrationTest { private static final ProtobufSerializer serializer = new ProtobufSerializer(); static { Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); root.setLevel(Level.INFO); serializer.registerResource("META-INF/cluster.desc"); } private static ProtobufConfig protobufConfig = new ProtobufConfig(); private static final ProtobufClient protobufClient = new ProtobufClient(new IoExecutors(), serializer, new ProtobufConfig()); private static final AdminContext admin = AdminContextJaxrsProxy.get("localhost", 8080); private static final Westty w1 = new Westty("w1"); private static final Westty w2 = new Westty("w2"); private static final Westty w3 = new Westty("w3"); // @BeforeClass public static void beforeClass() throws Throwable { // make sure that we can force the xml bean manager // even though the jpa bean manager normally would // take precedence.. System.setProperty(BeanManager.class.getName(), "org.deephacks.tools4j.config.internal.core.xml.XmlBeanManager"); w1.startup(); createServers("w1", "w2", "w3"); w2.startup(); w3.startup(); } // @AfterClass public static void afterClass() throws Throwable { w1.shutdown(); w2.shutdown(); w3.shutdown(); } /** * Test jaxrs and that each server have correct ServerName. */ // @Test public void test_servers_have_correct_names() { String path = ClusterEndpoint.JAXRS_PATH + "/getServerName"; String serverName = httpGet(path, 0); assertThat(serverName, is("w1")); serverName = httpGet(path, 1); assertThat(serverName, is("w2")); serverName = httpGet(path, 2); assertThat(serverName, is("w3")); } /** * Test jaxrs and that each server have a correct view of members in * the cluster. */ // @Test public void test_servers_have_correct_cluster_memberhip_view(){ String path = ClusterEndpoint.JAXRS_PATH + "/getClusterMemberPorts"; int base = ServerConfig.DEFAULT_CLUSTER_PORT; // w1 List<Integer> ports = JsonUtil.getPorts(httpGet(path, 0)); assertTrue(ports.containsAll(Arrays.asList(base,base+1,base+2))); // w2 ports = JsonUtil.getPorts(httpGet(path, 1)); assertTrue(ports.containsAll(Arrays.asList(base,base+1,base+2))); // w3 ports = JsonUtil.getPorts(httpGet(path, 2)); assertTrue(ports.containsAll(Arrays.asList(base,base+1,base+2))); } /** * Test that each server can receive a protobuf message and send it forward * onto the eventbus message to be received by any server (but only one) * in the cluster. */ // @Test public void test_servers_eventbus_send_to_cluster_members() throws Exception { String msg = "w1"; // w1 asyncSendProtobuf(msg, 0); List<String> all = new ArrayList<>(); all.addAll(getSendProtobuf(0)); all.addAll(getSendProtobuf(1)); all.addAll(getSendProtobuf(2)); assertThat(all.size(), is(1)); assertThat(all.get(0), is(msg)); // w2 msg = "w2"; asyncSendProtobuf(msg, 1); all = new ArrayList<>(); all.addAll(getSendProtobuf(0)); all.addAll(getSendProtobuf(1)); all.addAll(getSendProtobuf(2)); assertThat(all.size(), is(1)); assertThat(all.get(0), is(msg)); // w3 msg = "w3"; asyncSendProtobuf(msg, 2); all = new ArrayList<>(); all.addAll(getSendProtobuf(0)); all.addAll(getSendProtobuf(1)); all.addAll(getSendProtobuf(2)); assertThat(all.size(), is(1)); assertThat(all.get(0), is(msg)); } /** * Test that each server can receive a protobuf message and forward * it onto the eventbus message to be published to all members in the cluster. */ // @Test public void test_servers_eventbus_publish_to_cluster_members() throws Exception { String msg = "w1"; // w1 asyncPublishProtobuf(msg, 0); List<String> msgs = getPublishProtobuf(0); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(1); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(2); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); // w2 msg = "w2"; asyncPublishProtobuf(msg, 1); msgs = getPublishProtobuf(0); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(1); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(2); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); // w3 msg = "w3"; asyncPublishProtobuf(msg, 2); msgs = getPublishProtobuf(0); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(1); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); msgs = getPublishProtobuf(2); assertThat(msgs.size(), is(1)); assertThat(msgs.get(0), is(msg)); } private String httpGet(String path, int num) { JaxrsClient client = new JaxrsClient(ServerConfig.DEFAULT_IP_ADDRESS, ServerConfig.DEFAULT_HTTP_PORT + num); return client.gethttp(path); } private void asyncSendProtobuf(String msg, Integer num) throws Exception { Integer channelId = protobufClient.connect(new InetSocketAddress(protobufConfig.getPort() + num)); AsyncSendRequest req = AsyncSendRequest.newBuilder().setMsg(msg).build(); protobufClient.callAsync(channelId, req); Thread.sleep(500); protobufClient.disconnect(channelId); } private List<String> getSendProtobuf(Integer num) throws IOException { Integer channelId = protobufClient.connect(new InetSocketAddress(protobufConfig.getPort() + num)); GetSendRequest req = GetSendRequest.newBuilder().build(); GetSendResponse res = (GetSendResponse) protobufClient.callSync(channelId, req); protobufClient.disconnect(channelId); return res.getServerMsgList(); } private void asyncPublishProtobuf(String msg, Integer num) throws Exception { Integer channelId = protobufClient.connect(new InetSocketAddress(protobufConfig.getPort() + num)); AsyncPublishRequest req = AsyncPublishRequest.newBuilder().setMsg(msg).build(); protobufClient.callAsync(channelId, req); Thread.sleep(500); protobufClient.disconnect(channelId); } private List<String> getPublishProtobuf(Integer num) throws IOException { Integer channelId = protobufClient.connect(new InetSocketAddress(protobufConfig.getPort() + num)); GetPublishRequest req = GetPublishRequest.newBuilder().build(); GetPublishResponse res = (GetPublishResponse) protobufClient.callSync(channelId, req); protobufClient.disconnect(channelId); return res.getServerMsgList(); } public static void createServers(String... serverNames) throws Throwable { ClusterConfig cluster = new ClusterConfig(); for (int i = 0; i < serverNames.length; i++){ ServerConfig server = new ServerConfig(serverNames[i]); server.setHttpPort(ServerConfig.DEFAULT_HTTP_PORT + i); server.setClusterPort(ServerConfig.DEFAULT_CLUSTER_PORT + i); admin.createObject(server); cluster.addServer(server); ProtobufConfig proto = new ProtobufConfig(serverNames[i]); proto.setPort(protobufConfig.getPort() + i); admin.createObject(proto); SockJsConfig sockjs = new SockJsConfig(serverNames[i]); sockjs.setHttpPort(SockJsConfig.DEFAULT_HTTP_PORT + i); sockjs.setEventBusPort(SockJsConfig.DEFAULT_EVENTBUS_PORT + i); admin.createObject(sockjs); } admin.createObject(cluster); } }