/** * Copyright 2015 Santhosh Kumar Tekuri * * The JLibs authors license this file to you 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 jlibs.wamp4j; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import jlibs.wamp4j.client.ClientOperator; import jlibs.wamp4j.client.ProcedureOperator; import jlibs.wamp4j.client.WAMPClient; import jlibs.wamp4j.error.*; import jlibs.wamp4j.msg.CallMessage; import jlibs.wamp4j.msg.ErrorMessage; import jlibs.wamp4j.msg.InvocationMessage; import jlibs.wamp4j.msg.ResultMessage; import jlibs.wamp4j.netty.NettyClientEndpoint; import jlibs.wamp4j.netty.NettyServerEndpoint; import jlibs.wamp4j.router.RouterOperator; import jlibs.wamp4j.router.WAMPRouter; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; import java.util.ArrayList; import java.util.List; import static com.fasterxml.jackson.databind.node.JsonNodeFactory.instance; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** * @author Santhosh Kumar Tekuri */ public class RPCTest{ private URI uri = URI.create("ws://localhost:8080/wamp4j"); private RouterOperator router; private ClientOperator jlibsClient1; private ClientOperator jlibsClient2; private ClientOperator marsClient; @BeforeClass(description="starts router and clients") public void start() throws Throwable{ router = new RouterOperator(new WAMPRouter(new NettyServerEndpoint(), uri)); router.bind(); jlibsClient1 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient1.connect(); jlibsClient2 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient2.connect(); marsClient = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "mars")); marsClient.connect(); } @Test(description="register and unregister twice from different client under same realm") public void test1() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"); p1.registerWith(jlibsClient1); p1.unregister(); p1.registerWith(jlibsClient2); p1.unregister(); } @Test(description="registering same uri twice with different clients under same realm") public void test2() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"); p1.registerWith(jlibsClient1); ProcedureOperator p2 = new ProcedureOperator("p1"); try{ p2.registerWith(jlibsClient2); }catch(ProcedureAlreadyExistsException ex){ assertEquals(ex.getErrorCode(), ErrorCode.procedureAlreadyExists("p1")); } p1.unregister(); } @Test(description="registering same uri twice under different realms") public void test3() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"); p1.registerWith(jlibsClient1); ProcedureOperator p2 = new ProcedureOperator("p1"); p2.registerWith(marsClient); p2.unregister(); p1.unregister(); } @Test(description="test echo service") public void test4() throws Throwable{ try{ jlibsClient1.call(null, "p1", null, null); throw new RuntimeException("exception should occur"); }catch(NoSuchProcedureException ex){ assertEquals(ex.getErrorCode(), ErrorCode.noSuchProcedure("p1")); } ProcedureOperator p1 = new ProcedureOperator("p1"){ @Override protected void onRequest(WAMPClient client, InvocationMessage invocation){ client.reply(invocation.yield(invocation.details, invocation.arguments, invocation.argumentsKw)); } }; p1.registerWith(jlibsClient2); ResultMessage result = jlibsClient1.call(null, "p1", null, null); assertEquals(result.details, instance.objectNode()); assertEquals(result.arguments, null); assertEquals(result.argumentsKw, null); ArrayNode arguments = instance.arrayNode().add("arg"); result = jlibsClient1.call(null, "p1", arguments, null); assertEquals(result.details, instance.objectNode()); assertEquals(result.arguments, arguments); assertEquals(result.argumentsKw, null); ObjectNode options = instance.objectNode().put("option1", "value1"); ObjectNode argumentsKw = instance.objectNode().put("key", "value"); result = jlibsClient1.call(options, "p1", arguments, argumentsKw); assertEquals(result.details, options); assertEquals(result.arguments, arguments); assertEquals(result.argumentsKw, argumentsKw); p1.unregister(); try{ jlibsClient1.call(null, "p1", null, null); throw new RuntimeException("exception should occur"); }catch(NoSuchProcedureException ex){ assertEquals(ex.getErrorCode(), ErrorCode.noSuchProcedure("p1")); } } @Test(description="test rpc error") public void test5() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"){ @Override protected void onRequest(WAMPClient client, InvocationMessage invocation){ client.reply(invocation.error(invocation.details, "p1.error", invocation.arguments, invocation.argumentsKw)); } }; p1.registerWith(jlibsClient2); ArrayNode arguments = instance.arrayNode().add("arg"); ObjectNode options = instance.objectNode().put("option1", "value1"); ObjectNode argumentsKw = instance.objectNode().put("key", "value"); try{ jlibsClient1.call(options, "p1", arguments, argumentsKw); throw new RuntimeException("exception should occur"); }catch(WAMPException wex){ ErrorMessage error = new ErrorMessage(CallMessage.ID, -1, options, "p1.error", arguments, argumentsKw); assertEquals(wex.getErrorCode(), new ErrorCode(error)); } p1.unregister(); try{ jlibsClient1.call(null, "p1", null, null); throw new RuntimeException("exception should occur"); }catch(NoSuchProcedureException ex){ assertEquals(ex.getErrorCode(), ErrorCode.noSuchProcedure("p1")); } } @Test(description="when caller closed before callee replies") public void test6() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"){ @Override protected void onRequest(WAMPClient client, InvocationMessage invocation){ jlibsClient2.client.close(); } }; p1.registerWith(jlibsClient1); try{ jlibsClient2.call(null, "p1", null, null); }catch(SystemShutdownException ex){ assertEquals(ex.getErrorCode(), ErrorCode.systemShutdown()); } p1.unregister(); jlibsClient2 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient2.connect(); } @Test(description="when callee closed before sending replies") public void test7() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"){ @Override protected void onRequest(WAMPClient client, InvocationMessage invocation){ client.close(); } }; p1.registerWith(jlibsClient1); try{ jlibsClient2.call(null, "p1", null, null); }catch(NoSuchProcedureException ex){ assertEquals(ex.getErrorCode(), ErrorCode.noSuchProcedure("p1")); } p1.assertUnregistered(); jlibsClient1 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient1.connect(); } @Test(description="when router closed before caller receives reply") public void test8() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"){ @Override protected void onRequest(WAMPClient client, InvocationMessage invocation){ router.router.close(); } }; p1.registerWith(jlibsClient1); try{ jlibsClient2.call(null, "p1", null, null); }catch(SystemShutdownException ex){ assertEquals(ex.getErrorCode(), ErrorCode.systemShutdown()); } p1.assertUnregistered(); jlibsClient1.assertClosed(); jlibsClient2.assertClosed(); start(); } @Test(description="when client closes, router should remove all its registrations") public void test9() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"); p1.registerWith(jlibsClient1); ProcedureOperator p2 = new ProcedureOperator("p1"); try{ p2.registerWith(jlibsClient2); }catch(ProcedureAlreadyExistsException ex){ assertEquals(ex.getErrorCode(), ErrorCode.procedureAlreadyExists("p1")); } jlibsClient1.close(); p2.registerWith(jlibsClient2); p2.unregister(); jlibsClient1 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient1.connect(); } @Test(description="when client killed, router should remove all its registrations") public void test10() throws Throwable{ ProcedureOperator p1 = new ProcedureOperator("p1"); p1.registerWith(jlibsClient1); ProcedureOperator p2 = new ProcedureOperator("p1"); try{ p2.registerWith(jlibsClient2); }catch(ProcedureAlreadyExistsException ex){ assertEquals(ex.getErrorCode(), ErrorCode.procedureAlreadyExists("p1")); } jlibsClient1.kill(); p2.registerWith(jlibsClient2); p2.unregister(); jlibsClient1 = new ClientOperator(new WAMPClient(new NettyClientEndpoint(), uri, "jlibs")); jlibsClient1.connect(); } @Test public void sessionCount() throws Throwable{ ResultMessage result = jlibsClient1.call(null, "wamp.session.count", null, null); assertEquals(result.arguments.get(0).intValue(), 2); } @Test public void sessionList() throws Throwable{ ResultMessage result = jlibsClient1.call(null, "wamp.session.list", null, null); List<Long> sessionIDs = new ArrayList<Long>(); sessionIDs.add(jlibsClient1.client.getSessionID()); sessionIDs.add(jlibsClient2.client.getSessionID()); for(JsonNode sessionID : result.arguments.get(0)) assertTrue(sessionIDs.remove(sessionID.longValue())); assertTrue(sessionIDs.isEmpty()); } @AfterClass(description="stops clients and router") public void stop() throws Throwable{ jlibsClient1.close(); jlibsClient2.close(); marsClient.close(); router.close(); } }