package org.webpieces.nio.test.tcp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import org.webpieces.util.logging.Logger;
import org.webpieces.nio.api.channels.Channel;
import org.webpieces.nio.api.channels.TCPChannel;
import org.webpieces.nio.api.deprecated.ChannelService;
import org.webpieces.nio.api.deprecated.ChannelServiceFactory;
import org.webpieces.nio.api.deprecated.ConnectionCallback;
import org.webpieces.nio.api.deprecated.Settings;
import org.webpieces.nio.api.handlers.DataListener;
import org.webpieces.nio.api.libs.BufferFactory;
import org.webpieces.nio.api.libs.BufferHelper;
import org.webpieces.nio.api.libs.FactoryCreator;
import org.webpieces.nio.api.testutil.CloneByteBuffer;
import org.webpieces.nio.api.testutil.HandlerForTests;
import org.webpieces.nio.api.testutil.MockDataHandler;
import org.webpieces.nio.api.testutil.MockNIOServer;
import biz.xsoftware.mock.CalledMethod;
import biz.xsoftware.mock.CloningBehavior;
import biz.xsoftware.mock.MockObject;
import biz.xsoftware.mock.testcase.MockTestCase;
public abstract class ZNioFailureSuperclass extends MockTestCase {
private static final Logger log = LoggerFactory.getLogger(ZNioFailureSuperclass.class);
private BufferFactory bufFactory;
private InetSocketAddress svrAddr;
private ChannelService chanMgr;
private InetAddress loopBack;
private InetSocketAddress loopBackAnyPort;
private BufferHelper helper = ChannelServiceFactory.bufferHelper(null);
private MockObject mockHandler;
private MockObject mockConnect;
private TCPChannel client1;
private MockNIOServer mockServer;
protected abstract ChannelService getClientChanMgr();
protected abstract ChannelService getServerChanMgr();
protected abstract Settings getClientFactoryHolder();
protected abstract Settings getServerFactoryHolder();
protected abstract String getChannelImplName();
protected abstract String getServerChannelImplName();
public ZNioFailureSuperclass(String name) {
super(name);
if(bufFactory == null) {
Map<String, Object> map = new HashMap<String, Object>();
map.put(FactoryCreator.KEY_IS_DIRECT, false);
FactoryCreator creator = FactoryCreator.createFactory(null);
bufFactory = creator.createBufferFactory(map);
}
}
protected void setUpImpl() throws Exception {
HandlerForTests.setupLogging();
//here I keep using the same channel manager on purpose, just
//so we get testing between tests that the channel manager shutdown
//and started back up cleanly.....
if(chanMgr == null) {
chanMgr = getClientChanMgr();
}
if(mockServer == null) {
ChannelService svcChanMgr = getServerChanMgr();
mockServer = new MockNIOServer(svcChanMgr, getServerFactoryHolder());
}
chanMgr.start();
svrAddr = mockServer.start();
log.trace("server port ="+svrAddr);
loopBack = InetAddress.getByName("127.0.0.1");
loopBackAnyPort = new InetSocketAddress(loopBack, 0);
mockHandler = createMock(DataListener.class);
mockHandler.setDefaultBehavior("incomingData", new CloneByteBuffer());
mockConnect = createMock(ConnectionCallback.class);
client1 = chanMgr.createTCPChannel("ClientChannel", getClientFactoryHolder());
}
protected void tearDownImpl() throws Exception {
chanMgr.stop();
chanMgr = null;
mockServer.stop();
// try {
// HandlerForTests.checkForWarnings();
// fail("There should be warnings in the log and there was none");
// } catch(LogHasWarningException e) {
// }
}
public void testClientThrowsIntoConnectCallback() throws Exception {
setNumberOfExpectedWarnings(1);
log.info("hello");
//make sure we are testing the right one....
Class c = Class.forName(getChannelImplName());
assertEquals("should be instance of correct channel type", c, client1.getClass());
log.info("class name"+client1.getClass().getName());
String msg = "some exception message";
IOException e = new IOException(msg);
mockConnect.addThrowException("connected", e);
client1.bind(loopBackAnyPort);
client1.oldConnect(svrAddr, (ConnectionCallback)mockConnect);
client1.registerForReads((DataListener)mockHandler);
mockConnect.expect("connected");
TCPChannel svrChan = expectServerChannel(mockServer, c);
verifyDataPassing(svrChan);
verifyTearDown();
}
static TCPChannel expectServerChannel(MockNIOServer mockServer, Class c) {
CalledMethod method = mockServer.expect(MockNIOServer.CONNECTED);
TCPChannel svrChan = (TCPChannel)method.getAllParams()[0];
assertEquals("should be instance of correct channel type", c, svrChan.getClass());
return svrChan;
}
public void testClientThrowsIntoDataHandlerIncomingData() throws Exception {
setNumberOfExpectedWarnings(1);
//make sure we are testing the right one....
Class c = Class.forName(getChannelImplName());
assertEquals("should be instance of correct channel type", c, client1.getClass());
mockHandler.addBehavior("incomingData", new ThrowAndClone());
log.info("class name"+client1.getClass());
client1.bind(loopBackAnyPort);
client1.oldConnect(svrAddr, (ConnectionCallback)mockConnect);
client1.registerForReads((DataListener)mockHandler);
mockConnect.expect("connected");
TCPChannel svrChan = expectServerChannel(mockServer, c);
verifyDataPassing(svrChan);
verifyTearDown();
}
private static class ThrowAndClone implements CloningBehavior {
public void incomingData(Channel channel, ByteBuffer b) {
throw new RuntimeException("testing");
}
public Object[] incomingDataCloner(Channel channel, ByteBuffer chunk) {
return new Object[] { channel, CloneByteBuffer.clone(chunk) };
}
}
public void testClientThrowsIntoDataHandlerFarEndClosed() throws Exception {
setNumberOfExpectedWarnings(1);
//make sure we are testing the right one....
Class c = Class.forName(getChannelImplName());
assertEquals("should be instance of correct channel type", c, client1.getClass());
String msg = "some exception message";
IOException e = new IOException(msg);
mockServer.addThrowException("farEndClosed", e);
client1.bind(loopBackAnyPort);
client1.oldConnect(svrAddr, (ConnectionCallback)mockConnect);
client1.registerForReads((DataListener)mockHandler);
mockConnect.expect("connected");
TCPChannel svrChan = expectServerChannel(mockServer, c);
verifyDataPassing(svrChan);
verifyTearDown();
//shutdown of threaded CM is complicated...set stop method on threaded CM.
//We must sleep or thread could be interrupted and never log an error.
//This is a race condition, but only when we are stopping the ChannelManager
specialCaseThreadedCM();
}
protected void specialCaseThreadedCM() throws InterruptedException {
}
// public void testClientThrowsIntoAcceptHandlerConnect() throws Exception {
// setNumberOfExpectedWarnings(1);
//
// //make sure we are testing the right one....
// Class c = Class.forName(getChannelImplName());
// assertEquals("should be instance of correct channel type", c, client1.getClass());
//
// String msg = "some exception message";
// IOException e = new IOException(msg);
// mockServer.addThrowException("connected", e);
//
// client1.bind(loopBackAnyPort);
// client1.oldConnect(svrAddr, (ConnectionCallback)mockConnect);
// client1.registerForReads((DataListener)mockHandler);
//
// mockConnect.expect("connected");
// TCPChannel svrChan = expectServerChannel(mockServer, c);
//
// verifyDataPassing(svrChan);
// verifyTearDown();
// }
private ByteBuffer verifyDataPassing(TCPChannel svrChan) throws Exception {
ByteBuffer b = ByteBuffer.allocate(10);
helper.putString(b, "de");
helper.doneFillingBuffer(b);
int expectedWrote = b.remaining();
int actualWrite = client1.oldWrite(b);
assertEquals(expectedWrote, actualWrite);
CalledMethod m = mockServer.expect(MockNIOServer.INCOMING_DATA);
TCPChannel actualChannel = (TCPChannel)m.getAllParams()[0];
Class c = Class.forName(getChannelImplName());
assertEquals("should be correct type of channel", c, actualChannel.getClass());
ByteBuffer actualBuf = (ByteBuffer)m.getAllParams()[1];
String result = helper.readString(actualBuf, actualBuf.remaining());
log.info("result len="+result.length());
assertEquals("de", result);
b.rewind();
svrChan.oldWrite(b);
m = mockHandler.expect(MockDataHandler.INCOMING_DATA);
actualBuf = (ByteBuffer)m.getAllParams()[1];
log.info("buffer remain="+actualBuf.remaining());
result = helper.readString(actualBuf, actualBuf.remaining());
log.info("---1st char="+(result.substring(0, 1).equals("de".substring(0, 1))));
log.info("---2nd char="+(result.substring(1, 2).equals("de".substring(1, 2))));
log.info("substring='"+result.substring(0,1)+"'");
log.info("len="+"de".length()+" 2ndlen="+result.length());
log.info("'de'"+" actual='"+result+"'"+" result="+("de".equals(result)));
assertEquals("de", result);
return b;
}
private void verifyTearDown() throws IOException {
client1.oldClose();
mockServer.expect(MockNIOServer.FAR_END_CLOSED);
}
protected Object getBufFactory() {
return bufFactory;
}
}