/** * 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.fabric.netty.rpc; import com.liferay.portal.fabric.netty.NettyTestUtil; import com.liferay.portal.fabric.netty.handlers.NettyChannelAttributes; import com.liferay.portal.kernel.concurrent.AsyncBroker; import com.liferay.portal.kernel.concurrent.DefaultNoticeableFuture; import com.liferay.portal.kernel.concurrent.NoticeableFuture; import com.liferay.portal.kernel.test.CaptureHandler; import com.liferay.portal.kernel.test.JDKLoggerTestUtil; import com.liferay.portal.kernel.test.ReflectionTestUtil; import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor; import io.netty.channel.embedded.EmbeddedChannel; import java.io.Serializable; import java.util.List; import java.util.concurrent.ConcurrentMap; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; /** * @author Shuyang Zhou */ public class RPCResponseTest { @ClassRule public static final CodeCoverageAssertor codeCoverageAssertor = CodeCoverageAssertor.INSTANCE; @Test public void testExecuteWithCancellation() throws Exception { doTestExecute(true, _RESULT, null); } @Test public void testExecuteWithException() throws Exception { doTestExecute(false, null, _throwable); } @Test public void testExecuteWithResult() throws Exception { doTestExecute(false, _RESULT, null); } @Test public void testToString() { RPCResponse<String> rpcResponse = new RPCResponse<>( _ID, true, _RESULT, _throwable); Assert.assertEquals( "{cancelled=true, id=" + _ID + ", result=" + _RESULT + ", throwable=" + _throwable + "}", rpcResponse.toString()); } protected void doTestExecute( boolean cancelled, String result, Throwable throwable) throws Exception { // No future exist RPCResponse<String> rpcResponse = new RPCResponse<>( _ID, cancelled, result, throwable); try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( RPCResponse.class.getName(), Level.SEVERE)) { rpcResponse.execute(_embeddedChannel); List<LogRecord> logRecords = captureHandler.getLogRecords(); Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); LogRecord logRecord = logRecords.get(0); if (cancelled) { Assert.assertEquals( "Unable to place cancellation because no future exists " + "with ID " + _ID, logRecord.getMessage()); } else if (throwable != null) { Assert.assertEquals( "Unable to place exception because no future exists with " + "ID " + _ID, logRecord.getMessage()); Assert.assertSame(throwable, logRecord.getThrown()); } else { Assert.assertEquals( "Unable to place result " + result + " because no future exists with ID " + _ID, logRecord.getMessage()); } } // Have futures, with log try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( RPCResponse.class.getName(), Level.FINEST)) { AsyncBroker<Long, Serializable> asyncBroker = NettyChannelAttributes.getAsyncBroker(_embeddedChannel); NoticeableFuture<Serializable> noticeableFuture = asyncBroker.post( _ID); rpcResponse.execute(_embeddedChannel); List<LogRecord> logRecords = captureHandler.getLogRecords(); if (!cancelled) { Assert.assertTrue(logRecords.isEmpty()); return; } Assert.assertTrue(noticeableFuture.isCancelled()); Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); LogRecord logRecord = logRecords.remove(0); Assert.assertEquals( "Cancelled future with ID " + _ID, logRecord.getMessage()); DefaultNoticeableFuture<Serializable> defaultNoticeableFuture = new DefaultNoticeableFuture<>(); defaultNoticeableFuture.cancel(true); ConcurrentMap<Long, DefaultNoticeableFuture<Serializable>> defaultNoticeableFutures = ReflectionTestUtil.getFieldValue( asyncBroker, "_defaultNoticeableFutures"); defaultNoticeableFutures.put(_ID, defaultNoticeableFuture); rpcResponse.execute(_embeddedChannel); Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); logRecord = logRecords.remove(0); Assert.assertEquals( "Unable to cancel future with ID " + _ID + " because it is already completed", logRecord.getMessage()); } // Have futures, without log try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( RPCResponse.class.getName(), Level.OFF)) { AsyncBroker<Long, Serializable> asyncBroker = NettyChannelAttributes.getAsyncBroker(_embeddedChannel); NoticeableFuture<Serializable> noticeableFuture = asyncBroker.post( _ID); rpcResponse.execute(_embeddedChannel); Assert.assertTrue(noticeableFuture.isCancelled()); DefaultNoticeableFuture<Serializable> defaultNoticeableFuture = new DefaultNoticeableFuture<>(); defaultNoticeableFuture.cancel(true); ConcurrentMap<Long, DefaultNoticeableFuture<Serializable>> defaultNoticeableFutures = ReflectionTestUtil.getFieldValue( asyncBroker, "_defaultNoticeableFutures"); defaultNoticeableFutures.put(_ID, defaultNoticeableFuture); rpcResponse.execute(_embeddedChannel); } } private static final long _ID = System.currentTimeMillis(); private static final String _RESULT = "This is the result."; private final EmbeddedChannel _embeddedChannel = NettyTestUtil.createEmptyEmbeddedChannel(); private final Throwable _throwable = new Throwable( "This is the throwable."); }