/* * Copyright (C) 2015 SoftIndex LLC. * * Licensed 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 io.datakernel.stream.net; import com.google.common.collect.Lists; import com.google.common.net.InetAddresses; import com.google.gson.Gson; import io.datakernel.async.CompletionCallback; import io.datakernel.async.ConnectCallback; import io.datakernel.async.IgnoreCompletionCallback; import io.datakernel.bytebuf.ByteBufPool; import io.datakernel.eventloop.AsyncTcpSocket; import io.datakernel.eventloop.AsyncTcpSocketImpl; import io.datakernel.eventloop.Eventloop; import io.datakernel.eventloop.SimpleServer; import io.datakernel.eventloop.SimpleServer.SocketHandlerProvider; import io.datakernel.stream.StreamConsumers; import io.datakernel.stream.StreamProducers; import io.datakernel.stream.net.Messaging.ReceiveMessageCallback; import io.datakernel.stream.processor.StreamBinaryDeserializer; import io.datakernel.stream.processor.StreamBinarySerializer; import org.junit.Before; import org.junit.Test; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.List; import static io.datakernel.bytebuf.ByteBufPool.*; import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError; import static io.datakernel.serializer.asm.BufferSerializers.longSerializer; import static junit.framework.TestCase.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @SuppressWarnings("unchecked") public class MessagingWithBinaryStreamingTest { private static final int LISTEN_PORT = 4821; private static final InetSocketAddress address = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), LISTEN_PORT); @Before public void setUp() throws Exception { ByteBufPool.clear(); ByteBufPool.setSizes(0, Integer.MAX_VALUE); } @Test public void testPing() throws Exception { final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); SocketHandlerProvider socketHandlerProvider = new SocketHandlerProvider() { @Override public AsyncTcpSocket.EventHandler createSocketHandler(AsyncTcpSocket asyncTcpSocket) { MessagingWithBinaryStreaming<Integer, Integer> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), Integer.class, new Gson(), Integer.class)); pong(messaging); return messaging; } void pong(final Messaging<Integer, Integer> messaging) { messaging.receive(new ReceiveMessageCallback<Integer>() { @Override public void onReceive(Integer msg) { messaging.send(msg, IgnoreCompletionCallback.create()); pong(messaging); } @Override public void onReceiveEndOfStream() { messaging.close(); } @Override public void onException(Exception e) { messaging.close(); } }); } }; SimpleServer server = SimpleServer.create(eventloop, socketHandlerProvider) .withListenAddress(address) .withAcceptOnce(); server.listen(); eventloop.connect(address, new ConnectCallback() { void ping(int n, final Messaging<Integer, Integer> messaging) { messaging.send(n, IgnoreCompletionCallback.create()); messaging.receive(new ReceiveMessageCallback<Integer>() { @Override public void onReceive(Integer msg) { if (msg > 0) { ping(msg - 1, messaging); } else { messaging.close(); } } @Override public void onReceiveEndOfStream() { // empty } @Override public void onException(Exception e) { messaging.close(); } }); } @Override public void onConnect(SocketChannel socketChannel) { AsyncTcpSocketImpl asyncTcpSocket = AsyncTcpSocketImpl.wrapChannel(eventloop, socketChannel); MessagingWithBinaryStreaming<Integer, Integer> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), Integer.class, new Gson(), Integer.class)); ping(3, messaging); asyncTcpSocket.setEventHandler(messaging); asyncTcpSocket.register(); } @Override public void onException(Exception exception) { fail("Test Exception: " + exception); } }); eventloop.run(); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } @Test public void testMessagingDownload() throws Exception { final List<Long> source = Lists.newArrayList(); // for (long i = 0; i < 100; i++) { // source.add(i); // } final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); List<Long> l = new ArrayList<>(); final StreamConsumers.ToList<Long> consumerToList = StreamConsumers.toList(eventloop, l); SocketHandlerProvider socketHandlerProvider = new SocketHandlerProvider() { @Override public AsyncTcpSocket.EventHandler createSocketHandler(AsyncTcpSocket asyncTcpSocket) { final MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.receive(new ReceiveMessageCallback<String>() { @Override public void onReceive(String msg) { assertEquals("start", msg); StreamBinarySerializer<Long> streamSerializer = StreamBinarySerializer.create(eventloop, longSerializer()) .withDefaultBufferSize(1); StreamProducers.ofIterable(eventloop, source).streamTo(streamSerializer.getInput()); messaging.sendBinaryStreamFrom(streamSerializer.getOutput(), IgnoreCompletionCallback.create()); } @Override public void onReceiveEndOfStream() { } @Override public void onException(Exception e) { } }); return messaging; } }; SimpleServer server = SimpleServer.create(eventloop, socketHandlerProvider) .withListenAddress(address) .withAcceptOnce(); server.listen(); eventloop.connect(address, new ConnectCallback() { @Override public void onConnect(SocketChannel socketChannel) { AsyncTcpSocketImpl asyncTcpSocket = AsyncTcpSocketImpl.wrapChannel(eventloop, socketChannel); MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.send("start", IgnoreCompletionCallback.create()); messaging.sendEndOfStream(IgnoreCompletionCallback.create()); StreamBinaryDeserializer<Long> streamDeserializer = StreamBinaryDeserializer.create(eventloop, longSerializer()); messaging.receiveBinaryStreamTo(streamDeserializer.getInput(), IgnoreCompletionCallback.create()); streamDeserializer.getOutput().streamTo(consumerToList); asyncTcpSocket.setEventHandler(messaging); asyncTcpSocket.register(); } @Override public void onException(Exception e) { fail("Test Exception: " + e); } }); eventloop.run(); assertEquals(source, consumerToList.getList()); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } @Test public void testBinaryMessagingUpload() throws Exception { final List<Long> source = Lists.newArrayList(); for (long i = 0; i < 100; i++) { source.add(i); } final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); final StreamConsumers.ToList<Long> consumerToList = StreamConsumers.toList(eventloop); SocketHandlerProvider socketHandlerProvider = new SocketHandlerProvider() { @Override public AsyncTcpSocket.EventHandler createSocketHandler(AsyncTcpSocket asyncTcpSocket) { final MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.receive(new ReceiveMessageCallback<String>() { @Override public void onReceive(String message) { assertEquals("start", message); StreamBinaryDeserializer<Long> streamDeserializer = StreamBinaryDeserializer.create(eventloop, longSerializer()); messaging.receiveBinaryStreamTo(streamDeserializer.getInput(), IgnoreCompletionCallback.create()); streamDeserializer.getOutput().streamTo(consumerToList); messaging.sendEndOfStream(IgnoreCompletionCallback.create()); } @Override public void onReceiveEndOfStream() { } @Override public void onException(Exception e) { } }); return messaging; } }; SimpleServer server = SimpleServer.create(eventloop, socketHandlerProvider) .withListenAddress(address) .withAcceptOnce(); server.listen(); eventloop.connect(address, new ConnectCallback() { @Override public void onConnect(SocketChannel socketChannel) { AsyncTcpSocketImpl asyncTcpSocket = AsyncTcpSocketImpl.wrapChannel(eventloop, socketChannel); MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.send("start", IgnoreCompletionCallback.create()); StreamBinarySerializer<Long> streamSerializer = StreamBinarySerializer.create(eventloop, longSerializer()) .withDefaultBufferSize(1); StreamProducers.ofIterable(eventloop, source).streamTo(streamSerializer.getInput()); messaging.sendBinaryStreamFrom(streamSerializer.getOutput(), IgnoreCompletionCallback.create()); asyncTcpSocket.setEventHandler(messaging); asyncTcpSocket.register(); } @Override public void onException(Exception e) { fail("Test Exception: " + e); } }); eventloop.run(); assertEquals(source, consumerToList.getList()); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } @Test public void testBinaryMessagingUploadAck() throws Exception { final List<Long> source = Lists.newArrayList(); for (long i = 0; i < 100; i++) { source.add(i); } final boolean[] ack = new boolean[]{false}; final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); final StreamConsumers.ToList<Long> consumerToList = StreamConsumers.toList(eventloop); SocketHandlerProvider socketHandlerProvider = new SocketHandlerProvider() { @Override public AsyncTcpSocket.EventHandler createSocketHandler(AsyncTcpSocket asyncTcpSocket) { final MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.receive(new ReceiveMessageCallback<String>() { @Override public void onReceive(String msg) { assertEquals("start", msg); StreamBinaryDeserializer<Long> streamDeserializer = StreamBinaryDeserializer.create(eventloop, longSerializer()); streamDeserializer.getOutput().streamTo(consumerToList); messaging.receiveBinaryStreamTo(streamDeserializer.getInput(), new CompletionCallback() { @Override public void onComplete() { messaging.send("ack", IgnoreCompletionCallback.create()); messaging.sendEndOfStream(IgnoreCompletionCallback.create()); } @Override public void onException(Exception exception) { } }); } @Override public void onReceiveEndOfStream() { } @Override public void onException(Exception exception) { } }); return messaging; } }; SimpleServer server = SimpleServer.create(eventloop, socketHandlerProvider) .withListenAddress(address) .withAcceptOnce(); server.listen(); eventloop.connect(address, new ConnectCallback() { @Override public void onConnect(SocketChannel socketChannel) { AsyncTcpSocketImpl asyncTcpSocket = AsyncTcpSocketImpl.wrapChannel(eventloop, socketChannel); final MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.send("start", IgnoreCompletionCallback.create()); StreamBinarySerializer<Long> streamSerializer = StreamBinarySerializer.create(eventloop, longSerializer()) .withDefaultBufferSize(1); StreamProducers.ofIterable(eventloop, source).streamTo(streamSerializer.getInput()); messaging.sendBinaryStreamFrom(streamSerializer.getOutput(), IgnoreCompletionCallback.create()); messaging.receive(new ReceiveMessageCallback<String>() { @Override public void onReceive(String msg) { assertEquals("ack", msg); messaging.close(); ack[0] = true; } @Override public void onReceiveEndOfStream() { } @Override public void onException(Exception exception) { } }); asyncTcpSocket.setEventHandler(messaging); asyncTcpSocket.register(); } @Override public void onException(Exception e) { fail("Test Exception: " + e); } }); eventloop.run(); assertEquals(source, consumerToList.getList()); assertTrue(ack[0]); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } @Test public void testGsonMessagingUpload() throws Exception { final List<Long> source = Lists.newArrayList(); for (long i = 0; i < 100; i++) { source.add(i); } final Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); final StreamConsumers.ToList<Long> consumerToList = StreamConsumers.toList(eventloop); SocketHandlerProvider socketHandlerProvider = new SocketHandlerProvider() { @Override public AsyncTcpSocket.EventHandler createSocketHandler(AsyncTcpSocket asyncTcpSocket) { final MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.receive(new ReceiveMessageCallback<String>() { @Override public void onReceive(String msg) { assertEquals("start", msg); messaging.sendEndOfStream(IgnoreCompletionCallback.create()); StreamBinaryDeserializer<Long> streamDeserializer = StreamBinaryDeserializer.create(eventloop, longSerializer()); messaging.receiveBinaryStreamTo(streamDeserializer.getInput(), IgnoreCompletionCallback.create()); streamDeserializer.getOutput().streamTo(consumerToList); } @Override public void onReceiveEndOfStream() { } @Override public void onException(Exception exception) { } }); return messaging; } }; SimpleServer server = SimpleServer.create(eventloop, socketHandlerProvider) .withListenAddress(address) .withAcceptOnce(); server.listen(); eventloop.connect(address, new ConnectCallback() { @Override public void onConnect(SocketChannel socketChannel) { AsyncTcpSocketImpl asyncTcpSocket = AsyncTcpSocketImpl.wrapChannel(eventloop, socketChannel); MessagingWithBinaryStreaming<String, String> messaging = MessagingWithBinaryStreaming.create(eventloop, asyncTcpSocket, MessagingSerializers.ofGson(new Gson(), String.class, new Gson(), String.class)); messaging.send("start", IgnoreCompletionCallback.create()); StreamBinarySerializer<Long> streamSerializer = StreamBinarySerializer.create(eventloop, longSerializer()) .withDefaultBufferSize(1); StreamProducers.ofIterable(eventloop, source).streamTo(streamSerializer.getInput()); messaging.sendBinaryStreamFrom(streamSerializer.getOutput(), IgnoreCompletionCallback.create()); asyncTcpSocket.setEventHandler(messaging); asyncTcpSocket.register(); } @Override public void onException(Exception e) { fail("Test Exception: " + e); } } ); eventloop.run(); assertEquals(source, consumerToList.getList()); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } }