package com.googlecode.jsonrpc4j.server;
import com.fasterxml.jackson.databind.JsonNode;
import com.googlecode.jsonrpc4j.ConvertedParameterTransformer;
import com.googlecode.jsonrpc4j.InvocationListener;
import com.googlecode.jsonrpc4j.JsonRpcBasicServer;
import com.googlecode.jsonrpc4j.util.CustomTestException;
import com.googlecode.jsonrpc4j.util.Util;
import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.MockType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.List;
import static com.googlecode.jsonrpc4j.ErrorResolver.JsonError.METHOD_PARAMS_INVALID;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ID;
import static com.googlecode.jsonrpc4j.util.Util.createStream;
import static com.googlecode.jsonrpc4j.util.Util.decodeAnswer;
import static com.googlecode.jsonrpc4j.util.Util.getFromArrayWithId;
import static com.googlecode.jsonrpc4j.util.Util.intParam1;
import static com.googlecode.jsonrpc4j.util.Util.intParam2;
import static com.googlecode.jsonrpc4j.util.Util.messageOfStream;
import static com.googlecode.jsonrpc4j.util.Util.messageWithListParams;
import static com.googlecode.jsonrpc4j.util.Util.messageWithListParamsStream;
import static com.googlecode.jsonrpc4j.util.Util.multiMessageOfStream;
import static com.googlecode.jsonrpc4j.util.Util.param1;
import static com.googlecode.jsonrpc4j.util.Util.param2;
import static com.googlecode.jsonrpc4j.util.Util.param3;
import static com.googlecode.jsonrpc4j.util.Util.param4;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.eq;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@RunWith(EasyMockRunner.class)
public class JsonRpcBasicServerTest {
@Mock(type = MockType.NICE)
private ServiceInterface mockService;
private ByteArrayOutputStream byteArrayOutputStream;
private JsonRpcBasicServer jsonRpcServer;
@Before
public void setup() {
byteArrayOutputStream = new ByteArrayOutputStream();
jsonRpcServer = new JsonRpcBasicServer(Util.mapper, mockService, ServiceInterface.class);
}
@Test
public void receiveJsonRpcNotification() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(null, "testMethod", param1), byteArrayOutputStream);
assertEquals(0, byteArrayOutputStream.size());
}
@Test
public void callMethodWithTooFewParameters() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(createStream(messageOfStream(1, "testMethod", null)), byteArrayOutputStream);
assertEquals(METHOD_PARAMS_INVALID.code, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.ERROR).get(JsonRpcBasicServer.ERROR_CODE).intValue());
}
@Test
public void callMethodExactNumberOfParameters() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod", param1), byteArrayOutputStream);
assertEquals(param1, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callMethodWithExtraParameter() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod", param1, param2), byteArrayOutputStream);
assertEquals(METHOD_PARAMS_INVALID.code, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.ERROR).get(JsonRpcBasicServer.ERROR_CODE).intValue());
}
@Test
public void callOverloadedMethodExtraParamsAllowOn() throws Exception {
EasyMock.expect(mockService.overloadedMethod(param1, param2)).andReturn(param1 + param2);
EasyMock.replay(mockService);
jsonRpcServer.setAllowExtraParams(true);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", param1, param2, param3), byteArrayOutputStream);
assertEquals(param1 + param2, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callMethodWithTooFewParametersAllowOn() throws Exception {
EasyMock.expect(mockService.testMethod(anyString())).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.setAllowLessParams(true);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod"), byteArrayOutputStream);
assertEquals(param1, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callMethodExactNumberOfParametersAllowOn() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.setAllowExtraParams(true);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod", param1), byteArrayOutputStream);
assertEquals(param1, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callMethodWithExtraParameterAllowOn() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.setAllowExtraParams(true);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod", param1, param2), byteArrayOutputStream);
assertEquals(param1, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodNoParams() throws Exception {
final String noParam = "noParam";
EasyMock.expect(mockService.overloadedMethod()).andReturn(noParam);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod"), byteArrayOutputStream);
assertEquals(noParam, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodOneStringParam() throws Exception {
EasyMock.expect(mockService.overloadedMethod(param2)).andReturn(param2);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", param2), byteArrayOutputStream);
assertEquals(param2, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodOneIntParam() throws Exception {
EasyMock.expect(mockService.overloadedMethod(intParam1)).andReturn(param1 + intParam1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", intParam1), byteArrayOutputStream);
assertEquals(param1 + intParam1, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodTwoStringParams() throws Exception {
EasyMock.expect(mockService.overloadedMethod(param1, param2)).andReturn(param1 + param2);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", param1, param2), byteArrayOutputStream);
assertEquals(param1 + param2, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodTwoIntParams() throws Exception {
final String result = (intParam1 + intParam2) + "";
EasyMock.expect(mockService.overloadedMethod(intParam1, intParam2)).andReturn(result);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", intParam1, intParam2), byteArrayOutputStream);
assertEquals(result, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void callOverloadedMethodExtraParams() throws Exception {
EasyMock.expect(mockService.overloadedMethod(param1, param2)).andReturn(param1 + param2);
EasyMock.replay(mockService);
jsonRpcServer.setAllowExtraParams(true);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", param1, param2, param3), byteArrayOutputStream);
assertEquals(param1 + param2, decodeAnswer(byteArrayOutputStream).get(JsonRpcBasicServer.RESULT).textValue());
}
@Test
public void idIntegerType() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(intParam1, "testMethod", param1), byteArrayOutputStream);
assertTrue(decodeAnswer(byteArrayOutputStream).get(ID).isIntegralNumber());
}
@Test
public void idStringType() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
jsonRpcServer.handleRequest(messageWithListParamsStream(param1, "testMethod", param1), byteArrayOutputStream);
assertTrue(decodeAnswer(byteArrayOutputStream).get(ID).isTextual());
}
@Test
public void noId() throws Exception {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
EasyMock.replay(mockService);
int ok_code = jsonRpcServer.handleRequest(messageWithListParamsStream(null, "testMethod", param1), byteArrayOutputStream);
assertTrue(byteArrayOutputStream.toString(Util.JSON_ENCODING).isEmpty());
assertEquals(ok_code, JsonRpcBasicServer.CODE_OK);
}
/**
* The {@link com.googlecode.jsonrpc4j.JsonRpcBasicServer} is able to have an instance of
* {@link com.googlecode.jsonrpc4j.InvocationListener} configured for it. Prior to a
* method being invoked, the lister is notified and after the method is invoked, the
* listener is notified. This test checks that these two events are hit correctly in
* the case that an exception is raised when the method is invoked.
*/
@Test
@SuppressWarnings("unchecked")
public void callMethodThrowingWithInvocationListener() throws Exception {
final InvocationListener invocationListener = EasyMock.niceMock(InvocationListener.class);
Method m = ServiceInterface.class.getMethod("throwsMethod", String.class);
invocationListener.willInvoke(eq(m), anyObject(List.class));
invocationListener.didInvoke(eq(m), anyObject(List.class), EasyMock.isNull(), EasyMock.<Throwable>notNull(), EasyMock.geq(0L));
jsonRpcServer.setInvocationListener(invocationListener);
EasyMock.expect(mockService.throwsMethod(param1)).andThrow(new CustomTestException(param1));
EasyMock.replay(mockService, invocationListener);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "throwsMethod", param1), byteArrayOutputStream);
EasyMock.verify(invocationListener, mockService);
JsonNode json = decodeAnswer(byteArrayOutputStream);
assertNull(json.get(JsonRpcBasicServer.RESULT));
assertNotNull(json.get(JsonRpcBasicServer.ERROR));
}
/**
* The {@link com.googlecode.jsonrpc4j.JsonRpcBasicServer} is able to have an instance of
* {@link com.googlecode.jsonrpc4j.InvocationListener} configured for it. Prior to a
* method being invoked, the lister is notified and after the method is invoked, the
* listener is notified. This test checks that these two events are hit correctly
* when a method is invoked.
*/
@SuppressWarnings("unchecked")
@Test
public void callMethodWithInvocationListener() throws Exception {
final InvocationListener invocationListener = EasyMock.niceMock(InvocationListener.class);
Method m = ServiceInterface.class.getMethod("throwsMethod", String.class);
invocationListener.willInvoke(eq(m), anyObject(List.class));
invocationListener.didInvoke(eq(m), anyObject(List.class), EasyMock.notNull(), EasyMock.<Throwable>isNull(), EasyMock.geq(0L));
jsonRpcServer.setInvocationListener(invocationListener);
EasyMock.expect(mockService.throwsMethod(param1)).andReturn(param1);
EasyMock.replay(mockService, invocationListener);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "throwsMethod", param1), byteArrayOutputStream);
EasyMock.verify(invocationListener, mockService);
JsonNode json = decodeAnswer(byteArrayOutputStream);
assertEquals(param1, json.get(JsonRpcBasicServer.RESULT).textValue());
assertNull(json.get(JsonRpcBasicServer.ERROR));
}
@SuppressWarnings("unchecked")
@Test
public void callConvertedParameterTransformerShouldBeCalledIfSet() throws Exception {
final ConvertedParameterTransformer convertedParameterTransformer = EasyMock.niceMock(ConvertedParameterTransformer.class);
EasyMock.expect(mockService.testMethod(param1)).andReturn(param1);
jsonRpcServer.setConvertedParameterTransformer(convertedParameterTransformer);
EasyMock.expect(convertedParameterTransformer.transformConvertedParameters(anyObject(), anyObject(Object[].class))).andReturn(new Object[]{param1});
EasyMock.replay(convertedParameterTransformer);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "testMethod", param1), byteArrayOutputStream);
EasyMock.verify(convertedParameterTransformer);
}
@SuppressWarnings("unchecked")
@Test
public void callConvertedParameterTransformerShouldTransformTheParameters() throws Exception {
final ConvertedParameterTransformer convertedParameterTransformer = EasyMock.niceMock(ConvertedParameterTransformer.class);
String[] parameters = {param1, param2};
String[] expectedConvertedParameters = {param2, param1};
EasyMock.expect(mockService.overloadedMethod(param2, param1)).andReturn("converted");
jsonRpcServer.setConvertedParameterTransformer(convertedParameterTransformer);
EasyMock.expect(convertedParameterTransformer.transformConvertedParameters(anyObject(), anyObject(Object[].class))).andReturn(expectedConvertedParameters);
EasyMock.replay(mockService, convertedParameterTransformer);
jsonRpcServer.handleRequest(messageWithListParamsStream(1, "overloadedMethod", (Object[]) parameters), byteArrayOutputStream);
JsonNode json = decodeAnswer(byteArrayOutputStream);
assertEquals("converted", json.get(JsonRpcBasicServer.RESULT).textValue());
assertNull(json.get(JsonRpcBasicServer.ERROR));
}
@Test
public void multiMessageSimple() throws IOException {
EasyMock.expect(mockService.testMethod(param1)).andReturn(param2);
EasyMock.expect(mockService.overloadedMethod(intParam1)).andReturn(param1);
EasyMock.replay(mockService);
InputStream input = multiMessageOfStream(messageWithListParams(1, "testMethod", param1),
messageWithListParams(2, "overloadedMethod", intParam1));
jsonRpcServer.handleRequest(input, byteArrayOutputStream);
JsonNode json = decodeAnswer(byteArrayOutputStream);
assertTrue(json.isArray());
assertEquals(getFromArrayWithId(json, 1).get(JsonRpcBasicServer.RESULT).asText(), param2);
assertEquals(getFromArrayWithId(json, 2).get(JsonRpcBasicServer.RESULT).asText(), param1);
EasyMock.verify(mockService);
}
@Test
public void multiMessageOneOkOneError() throws IOException {
EasyMock.expect(mockService.overloadedMethod(param1)).andReturn(param2);
EasyMock.expect(mockService.throwsMethod(param3)).andThrow(new CustomTestException(param4));
EasyMock.replay(mockService);
InputStream input = multiMessageOfStream(messageWithListParams(1, "overloadedMethod", param1),
messageWithListParams(2, "throwsMethod", param3),
messageWithListParams(3, "testMethod"));
jsonRpcServer.handleRequest(input, byteArrayOutputStream);
JsonNode json = decodeAnswer(byteArrayOutputStream);
assertTrue(json.isArray());
assertEquals(getFromArrayWithId(json, 1).get(JsonRpcBasicServer.RESULT).asText(), param2);
assertEquals(getFromArrayWithId(json, 2).get(JsonRpcBasicServer.RESULT), null);
assertFalse(getFromArrayWithId(json, 2).get(JsonRpcBasicServer.ERROR).isNull());
assertEquals(getFromArrayWithId(json, 2).get(JsonRpcBasicServer.ERROR).get(JsonRpcBasicServer.DATA).get(JsonRpcBasicServer.ERROR_MESSAGE).asText(), param4);
EasyMock.verify(mockService);
}
// Service and service interfaces used in test
public interface ServiceInterface {
String testMethod(String param1);
String overloadedMethod();
String overloadedMethod(String stringParam1);
String overloadedMethod(String stringParam1, String stringParam2);
String overloadedMethod(int intParam1);
String overloadedMethod(int intParam1, int intParam2);
String throwsMethod(String param1) throws CustomTestException;
}
}