/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.voltcore.network;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestPicoNetwork extends TestCase {
ServerSocketChannel ssc;
SocketChannel networkChannel;
SocketChannel rawChannel;
PicoNetwork pn;
MockInputHandler handler = new MockInputHandler();
BlockingQueue<ByteBuffer> messages = new LinkedBlockingQueue<ByteBuffer>();
private class MockInputHandler extends VoltProtocolHandler {
volatile boolean startedCalled;
volatile boolean startingCalled;
volatile boolean stoppedCalled;
volatile boolean stoppingCalled;
Exception e;
@Override
public int getMaxRead() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void handleMessage(ByteBuffer message, Connection c) {
messages.offer(message);
}
@Override
public void started(Connection c) {
if (startedCalled) e = new Exception("Started called twice");
startedCalled = true;
}
@Override
public void starting(Connection c) {
if (startingCalled) e = new Exception("Starting called twice");
startingCalled = true;
}
@Override
public void stopped(Connection c) {
if (stoppedCalled) e = new Exception("Stopped called twice");
stoppedCalled = true;
}
@Override
public void stopping(Connection c) {
if (stoppingCalled) e = new Exception("Stopping called twice");
stoppingCalled = true;
}
@Override
public Runnable offBackPressure() {
return new Runnable() {
@Override
public void run() {
new Throwable("SHould never happen").printStackTrace();
System.exit(-1);
}
};
}
@Override
public Runnable onBackPressure() {
return new Runnable() {
@Override
public void run() {
new Throwable("SHould never happen").printStackTrace();
System.exit(-1);
}
};
}
@Override
public QueueMonitor writestreamMonitor() {
return null;
}
@Override
public long connectionId() {
return 0;
}
}
@Override
@Before
public void setUp() throws Exception {
ssc = ServerSocketChannel.open();
InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 21212);
ssc.bind(addr);
rawChannel = SocketChannel.open();
rawChannel.configureBlocking(false);
rawChannel.connect(addr);
networkChannel = ssc.accept();
rawChannel.finishConnect();
rawChannel.configureBlocking(true);
pn = new PicoNetwork(networkChannel);
handler = new MockInputHandler();
pn.start(handler, new HashSet<Long>());
}
@Override
@After
public void tearDown() throws Exception {
ssc.close();
networkChannel.close();
rawChannel.close();
pn.shutdownAsync();
messages.clear();
handler = null;
System.gc();
System.runFinalization();
}
@Test
public void testBasic() throws Exception {
ByteBuffer buf = ByteBuffer.allocate(5);
buf.putInt(1);
buf.position(0);
rawChannel.write(buf);
buf = messages.take();
assertTrue(handler.startedCalled);
assertTrue(handler.startingCalled);
rawChannel.close();
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 60000) {
if (handler.stoppedCalled == true && handler.stoppingCalled == true) break;
}
if (handler.e != null) throw new Exception(handler.e);
assertTrue(handler.stoppedCalled);
assertTrue(handler.stoppingCalled);
}
@Test
public void testLargeMessages() throws Exception {
ByteBuffer buf = ByteBuffer.allocate(1024 * 1024 * 30);
buf.putInt(buf.capacity() - 4);
buf.position(0);
while (buf.hasRemaining()) {
rawChannel.write(buf);
}
ByteBuffer receipt = messages.take();
assertEquals(receipt.capacity(), buf.capacity() - 4);
buf.clear();
pn.enqueue(buf.duplicate());
buf.clear();
while (buf.hasRemaining()) {
rawChannel.read(buf);
}
}
}