/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.kernel.nio.intraband.rpc;
import com.liferay.portal.kernel.concurrent.DefaultNoticeableFuture;
import com.liferay.portal.kernel.io.Deserializer;
import com.liferay.portal.kernel.io.Serializer;
import com.liferay.portal.kernel.nio.intraband.Datagram;
import com.liferay.portal.kernel.nio.intraband.SystemDataType;
import com.liferay.portal.kernel.nio.intraband.rpc.IntrabandRPCUtil.FutureCompletionHandler;
import com.liferay.portal.kernel.nio.intraband.test.MockIntraband;
import com.liferay.portal.kernel.nio.intraband.test.MockRegistrationReference;
import com.liferay.portal.kernel.process.ProcessCallable;
import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
/**
* @author Shuyang Zhou
*/
public class IntrabandRPCUtilTest {
@ClassRule
public static final CodeCoverageAssertor codeCoverageAssertor =
new CodeCoverageAssertor() {
@Override
public void appendAssertClasses(List<Class<?>> assertClasses) {
assertClasses.add(RPCResponse.class);
}
};
@Test
public void testConstructor() {
new IntrabandRPCUtil();
}
@Test
public void testExecuteFail() throws Exception {
Class<?> clazz = getClass();
PortalClassLoaderUtil.setClassLoader(clazz.getClassLoader());
final Exception exception = new Exception("Execution error");
MockIntraband mockIntraband = new MockIntraband() {
@Override
protected Datagram processDatagram(Datagram datagram) {
try {
Serializer serializer = new Serializer();
serializer.writeObject(new RPCResponse(exception));
return Datagram.createResponseDatagram(
datagram, serializer.toByteBuffer());
}
catch (Exception e) {
throw new RuntimeException();
}
}
};
MockRegistrationReference mockRegistrationReference =
new MockRegistrationReference(mockIntraband);
Future<String> futureResult = IntrabandRPCUtil.execute(
mockRegistrationReference, new TestProcessCallable());
try {
futureResult.get();
Assert.fail();
}
catch (ExecutionException ee) {
Throwable t = ee.getCause();
Assert.assertEquals(exception.getMessage(), t.getMessage());
}
}
@Test
public void testExecuteSuccess() throws Exception {
Class<?> clazz = getClass();
PortalClassLoaderUtil.setClassLoader(clazz.getClassLoader());
MockIntraband mockIntraband = new MockIntraband() {
@Override
protected Datagram processDatagram(Datagram datagram) {
Deserializer deserializer = new Deserializer(
datagram.getDataByteBuffer());
try {
Serializer serializer = new Serializer();
ProcessCallable<Serializable> processCallable =
deserializer.readObject();
serializer.writeObject(
new RPCResponse(processCallable.call()));
return Datagram.createResponseDatagram(
datagram, serializer.toByteBuffer());
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
};
MockRegistrationReference mockRegistrationReference =
new MockRegistrationReference(mockIntraband);
Future<String> futureResult = IntrabandRPCUtil.execute(
mockRegistrationReference, new TestProcessCallable());
Assert.assertEquals(
TestProcessCallable.class.getName(), futureResult.get());
}
@Test
public void testFutureCompletionHandler() throws Exception {
// Failed
DefaultNoticeableFuture<String> defaultNoticeableFuture =
new DefaultNoticeableFuture<>();
FutureCompletionHandler<String> futureCompletionHandler =
new FutureCompletionHandler<>(defaultNoticeableFuture);
futureCompletionHandler.delivered(null);
futureCompletionHandler.submitted(null);
IOException ioe = new IOException();
futureCompletionHandler.failed(null, ioe);
try {
defaultNoticeableFuture.get();
Assert.fail();
}
catch (ExecutionException ee) {
Assert.assertSame(ioe, ee.getCause());
}
// Class not found exception
defaultNoticeableFuture = new DefaultNoticeableFuture<>();
futureCompletionHandler = new FutureCompletionHandler<>(
defaultNoticeableFuture);
Serializer serializer = new Serializer();
serializer.writeObject(new TestProcessCallable());
ByteBuffer byteBuffer = serializer.toByteBuffer();
byteBuffer.put(76, (byte)CharPool.UPPER_CASE_S);
futureCompletionHandler.replied(
null,
Datagram.createRequestDatagram(
SystemDataType.RPC.getValue(), byteBuffer));
try {
defaultNoticeableFuture.get();
Assert.fail();
}
catch (ExecutionException ee) {
Throwable throwable = ee.getCause();
Assert.assertSame(
ClassNotFoundException.class, throwable.getClass());
}
// Timed out
defaultNoticeableFuture = new DefaultNoticeableFuture<>();
futureCompletionHandler = new FutureCompletionHandler<>(
defaultNoticeableFuture);
futureCompletionHandler.timedOut(null);
try {
defaultNoticeableFuture.get();
Assert.fail();
}
catch (CancellationException ce) {
}
}
private static class TestProcessCallable
implements ProcessCallable<String> {
@Override
public String call() {
return TestProcessCallable.class.getName();
}
private static final long serialVersionUID = 1L;
}
}