public void testUnregisterReregisterForReads() throws Exception {
    Class c = Class.forName(getChannelImplName());

    client1.bind(loopBackAnyPort);
    client1.oldConnect(svrAddr);

    TCPChannel svrChan = ZNioFailureSuperclass.expectServerChannel(mockServer, c);
    client1.registerForReads((DataListener) mockHandler);

    ByteBuffer b = verifyDataPassing(svrChan);

    client1.unregisterForReads();
    b.rewind();
    svrChan.oldWrite(b);
    Thread.sleep(5000);
    mockHandler.expect(MockObject.NONE);

    client1.registerForReads((DataListener) mockHandler);
    CalledMethod m = mockHandler.expect(MockNIOServer.INCOMING_DATA);
    ByteBuffer actualBuf = (ByteBuffer) m.getAllParams()[1];
    String result = helper.readString(actualBuf, actualBuf.remaining());
    assertEquals("de", result);

    verifyTearDown();
  }
  @Override
  protected void tearDown() throws Exception {
    if (!clientEngine.isClosed()) closeWithExpects(clientEngine, clientList);
    if (!serverEngine.isClosed()) closeWithExpects(serverEngine, serverList);

    HandlerForTests.checkForWarnings();
    clientList.expect(MockObject.NONE);
    serverList.expect(MockObject.NONE);
  }
  private ByteBuffer verifyDataPassing(TCPChannel svrChan) throws Exception {
    ByteBuffer b = ByteBuffer.allocate(10);
    helper.putString(b, "de");
    helper.doneFillingBuffer(b);
    int expectedWrote = b.remaining();
    log.fine("***********************************************");
    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());
    assertEquals("de", result);

    b.rewind();
    svrChan.oldWrite(b);

    m = mockHandler.expect(MockDataHandler.INCOMING_DATA);
    actualBuf = (ByteBuffer) m.getAllParams()[1];
    result = helper.readString(actualBuf, actualBuf.remaining());
    assertEquals("de", result);
    return b;
  }
  /**
   * Order between TCPChannel.connect and TCPChannel.registerForRead results in different code
   * paths...this is one of the tests.
   *
   * @throws Exception
   */
  public void testRegisterForReadsAfterConnect() throws Exception {
    // make sure we are testing the right one....
    Class c = Class.forName(getChannelImplName());
    assertEquals("should be instance of secure channel", c, client1.getClass());

    // no bind, just do connect to test port is not zero
    client1.oldConnect(svrAddr, (ConnectionCallback) mockConnect);
    mockConnect.expect("connected");
    log.info("connected");

    boolean isConnected = client1.isConnected();
    assertTrue("Client should be connected", isConnected);
    InetSocketAddress localAddr = client1.getLocalAddress();
    assertTrue("Port should not be 0", localAddr.getPort() != 0);

    TCPChannel svrChan = ZNioFailureSuperclass.expectServerChannel(mockServer, c);

    client1.registerForReads((DataListener) mockHandler);

    log.info("data passing");
    verifyDataPassing(svrChan);
    log.info("teardown");
    verifyTearDown();
    log.info("done");
  }
  @Override
  protected void setUp() throws Exception {
    HandlerForTests.setupLogging();

    serverList.setDefaultBehavior("packetEncrypted", new CloneByteBuffer());
    clientList.setDefaultBehavior("packetEncrypted", new CloneByteBuffer());
    SSLEngineFactory sslEngineFactory = new MockSSLEngineFactory();
    FactoryCreator creator = FactoryCreator.createFactory(null);

    SSLEngine wrappedSvr = sslEngineFactory.createEngineForServerSocket();
    serverEngine = creator.createSSLEngine("[serverAsynch] ", wrappedSvr, null);
    serverEngine.setListener((SSLListener) serverList);

    SSLEngine wrappedClient = sslEngineFactory.createEngineForSocket();
    clientEngine = creator.createSSLEngine("[clientEngine] ", wrappedClient, null);
    clientEngine.setListener((SSLListener) clientList);
  }
  public void testHalfPackets() throws Exception {
    clientEngine.beginHandshake();

    CalledMethod m = clientList.expect("packetEncrypted");
    ByteBuffer b = (ByteBuffer) m.getAllParams()[0];

    feedPacket(serverEngine, b);

    m = serverList.expect("runTask");
    Runnable r = (Runnable) m.getAllParams()[0];
    r.run();

    m = serverList.expect("packetEncrypted");
    b = (ByteBuffer) m.getAllParams()[0];
    log.fine("remain1=" + b.remaining());

    feedPacket(clientEngine, b);

    m = clientList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];
    r.run();

    String[] methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "packetEncrypted";
    CalledMethod[] methods = clientList.expect(methodNames);

    ByteBuffer b0 = (ByteBuffer) methods[0].getAllParams()[0];
    feedPacket(serverEngine, b0);

    m = serverList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];
    r.run();

    ByteBuffer b1 = (ByteBuffer) methods[1].getAllParams()[0];
    feedPacket(serverEngine, b1);

    ByteBuffer b2 = (ByteBuffer) methods[2].getAllParams()[0];
    feedPacket(serverEngine, b2);

    methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "encryptedLinkEstablished";
    methods = serverList.expect(methodNames);

    b0 = (ByteBuffer) methods[0].getAllParams()[0];
    feedPacket(clientEngine, b0);

    b1 = (ByteBuffer) methods[1].getAllParams()[0];
    feedPacket(clientEngine, b1);

    clientList.expect("encryptedLinkEstablished");
  }
  /**
   * This tests the situation where the Runnable must tell the engine to reprocess the buffer
   * itself.
   */
  public void testReallyDelayedRunTask() throws Exception {
    log.fine("B*******************************************");
    clientEngine.beginHandshake();
    CalledMethod m = clientList.expect("packetEncrypted");
    ByteBuffer b = (ByteBuffer) m.getAllParams()[0];

    serverEngine.feedEncryptedPacket(b, null);
    m = serverList.expect("runTask");
    Runnable r = (Runnable) m.getAllParams()[0];

    r.run();
    m = serverList.expect("packetEncrypted");
    b = (ByteBuffer) m.getAllParams()[0];

    clientEngine.feedEncryptedPacket(b, null);
    m = clientList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];

    r.run();
    String[] methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "packetEncrypted";
    CalledMethod[] methods = clientList.expect(methodNames);

    ByteBuffer b0 = (ByteBuffer) methods[0].getAllParams()[0];

    serverEngine.feedEncryptedPacket(b0, null);
    ByteBuffer b1 = (ByteBuffer) methods[1].getAllParams()[0];
    m = serverList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];

    serverEngine.feedEncryptedPacket(b1, null);
    ByteBuffer b2 = (ByteBuffer) methods[2].getAllParams()[0];

    serverEngine.feedEncryptedPacket(b2, null);
    String[] methodNames1 = new String[3];

    // THIS IS THE REALLY DELAYED RUN TASK run after all 3 packets are fed
    // to ssl engine
    r.run();

    methodNames1[0] = "packetEncrypted";
    methodNames1[1] = "packetEncrypted";
    methodNames1[2] = "encryptedLinkEstablished";
    CalledMethod[] methods1 = serverList.expect(methodNames1);

    ByteBuffer b01 = (ByteBuffer) methods1[0].getAllParams()[0];
    clientEngine.feedEncryptedPacket(b01, null);
    ByteBuffer b11 = (ByteBuffer) methods1[1].getAllParams()[0];
    clientEngine.feedEncryptedPacket(b11, null);

    clientList.expect("encryptedLinkEstablished");
    log.fine("E*******************************************");
  }
  public void testConnectClose() throws Exception {
    // make sure we are testing the right one....
    //        Class c = Class.forName(getChannelImplName());
    //        assertEquals("should be instance of secure channel", c, client1.getClass());

    // no bind, just do connect to test port is not zero
    client1.oldConnect(svrAddr, (ConnectionCallback) mockConnect);
    mockConnect.expect("connected");

    mockServer.expect(MockNIOServer.CONNECTED);

    verifyTearDown();
  }
  /**
   * This cannot pass on linux right now as warnings end up in the log from reads firing even though
   * there should be none if not connected. We can fix this later if it is needed.
   *
   * <p>Order between TCPChannel.connect and TCPChannel.registerForRead results in different code
   * paths...this is one of the tests.
   *
   * @throws Exception
   */
  public void xtestRegisterForReadsBeforeConnect() throws Exception {
    // make sure we are testing the right one....
    Class c = Class.forName(getChannelImplName());
    assertEquals("should be instance of correct channel type", c, client1.getClass());

    client1.bind(loopBackAnyPort);
    client1.registerForReads((DataListener) mockHandler);
    client1.oldConnect(svrAddr, (ConnectionCallback) mockConnect);
    mockConnect.expect("connected");

    boolean isConnected = client1.isConnected();
    assertTrue("Client should be connected", isConnected);

    TCPChannel svrChan = ZNioFailureSuperclass.expectServerChannel(mockServer, c);

    verifyDataPassing(svrChan);
    verifyTearDown();
  }
  /**
   * Test closing socket before ChannelManager shutdown works.
   *
   * @throws Exception
   */
  public void testCloseSvrSocketBeforeChannelMgrShutdown() throws Exception {
    Class c = Class.forName(getChannelImplName());
    client1.bind(loopBackAnyPort);
    client1.oldConnect(svrAddr);

    boolean isConnected = client1.isConnected();
    assertTrue("Client should be connected", isConnected);

    TCPChannel svrChan = ZNioFailureSuperclass.expectServerChannel(mockServer, c);
    client1.registerForReads((DataListener) mockHandler);

    verifyDataPassing(svrChan);

    svrChan.oldClose();

    // shutdown channel manager first
    mockServer.stop();

    mockHandler.expect(MockNIOServer.FAR_END_CLOSED);
  }
  /**
   * There was a bug where calling ChannelManager.shutdown before closing any sockets registered
   * with that ChannelManager cannot be closed...well, at least this test proves when we close the
   * test, the other side should receive that -1 indicating the far end closed the socket.
   *
   * @throws Exception
   */
  public void testCloseSocketAfterChannelMgrShutdown() throws Exception {
    Class c = Class.forName(getChannelImplName());

    client1.bind(loopBackAnyPort);
    client1.oldConnect(svrAddr);
    TCPChannel svrChan = ZNioFailureSuperclass.expectServerChannel(mockServer, c);

    client1.registerForReads((DataListener) mockHandler);

    verifyDataPassing(svrChan);

    // shutdown channel manager first....should all sockets be closed?  Right now
    // someone has to manually close all accepted sockets...ie. client responsibility.
    svrChan.oldClose();

    mockServer.stop();

    // notice the Channelmanager on the client side has not shut down so we should
    // see a close event....
    mockHandler.expect(MockNIOServer.FAR_END_CLOSED);
  }
  protected void setUp() 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.fine("server port =" + svrAddr);

    loopBack = InetAddress.getByName("127.0.0.1");
    loopBackAnyPort = new InetSocketAddress(loopBack, 0);

    mockHandler = MockObjectFactory.createMock(DataListener.class);
    mockHandler.setDefaultBehavior("incomingData", new CloneByteBuffer());
    mockConnect = MockObjectFactory.createMock(ConnectionCallback.class);
    client1 = chanMgr.createTCPChannel("ClientChannel", getClientFactoryHolder());
  }
  public void testRunInMiddleOfPacket() throws Exception {
    log.fine("B*******************************************");
    clientEngine.beginHandshake();
    CalledMethod m = clientList.expect("packetEncrypted");
    ByteBuffer b = (ByteBuffer) m.getAllParams()[0];

    serverEngine.feedEncryptedPacket(b, null);
    m = serverList.expect("runTask");
    Runnable r = (Runnable) m.getAllParams()[0];

    r.run();
    m = serverList.expect("packetEncrypted");
    b = (ByteBuffer) m.getAllParams()[0];

    clientEngine.feedEncryptedPacket(b, null);
    m = clientList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];

    r.run();
    String[] methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "packetEncrypted";
    CalledMethod[] methods = clientList.expect(methodNames);

    ByteBuffer b0 = (ByteBuffer) methods[0].getAllParams()[0];
    ByteBuffer b1 = (ByteBuffer) methods[1].getAllParams()[0];
    ByteBuffer b2 = (ByteBuffer) methods[2].getAllParams()[0];

    serverEngine.feedEncryptedPacket(b0, null);
    m = serverList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];

    int total = b1.remaining() + b2.remaining();
    ByteBuffer combined = ByteBuffer.allocate(total);

    int lim = b1.limit();
    b1.limit(3); // we only want to put part of b1 in payload
    combined.put(b1);
    helper.doneFillingBuffer(combined);
    serverEngine.feedEncryptedPacket(combined, null);

    // run the task after some of the previous packet fed, then feed rest of packet
    r.run();

    combined.clear();
    b1.limit(lim);
    combined.put(b1);
    combined.put(b2);

    helper.doneFillingBuffer(combined);
    serverEngine.feedEncryptedPacket(combined, null);

    String[] methodNames1 = new String[3];
    methodNames1[0] = "packetEncrypted";
    methodNames1[1] = "packetEncrypted";
    methodNames1[2] = "encryptedLinkEstablished";
    CalledMethod[] methods1 = serverList.expect(methodNames1);

    b0 = (ByteBuffer) methods1[0].getAllParams()[0];
    clientEngine.feedEncryptedPacket(b0, null);
    b1 = (ByteBuffer) methods1[1].getAllParams()[0];
    clientEngine.feedEncryptedPacket(b1, null);

    clientList.expect("encryptedLinkEstablished");
  }
  public void testOneAndHalfPackets() throws Exception {
    clientEngine.beginHandshake();

    CalledMethod m = clientList.expect("packetEncrypted");
    ByteBuffer b = (ByteBuffer) m.getAllParams()[0];
    serverEngine.feedEncryptedPacket(b, null);

    m = serverList.expect("runTask");
    Runnable r = (Runnable) m.getAllParams()[0];
    r.run();

    m = serverList.expect("packetEncrypted");
    b = (ByteBuffer) m.getAllParams()[0];
    clientEngine.feedEncryptedPacket(b, null);

    m = clientList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];
    r.run();

    String[] methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "packetEncrypted";
    CalledMethod[] methods = clientList.expect(methodNames);

    ByteBuffer b0 = (ByteBuffer) methods[0].getAllParams()[0];
    ByteBuffer b1 = (ByteBuffer) methods[1].getAllParams()[0];
    ByteBuffer b2 = (ByteBuffer) methods[2].getAllParams()[0];

    int total = b0.remaining() + b1.remaining() + b2.remaining();
    ByteBuffer combined = ByteBuffer.allocate(total);
    combined.put(b0);

    int lim = b1.limit();
    b1.limit(3); // we only want to put part of b1 in payload
    combined.put(b1);
    helper.doneFillingBuffer(combined);
    serverEngine.feedEncryptedPacket(combined, null);

    combined.clear();
    b1.limit(lim);
    combined.put(b1);
    combined.put(b2);

    helper.doneFillingBuffer(combined);
    serverEngine.feedEncryptedPacket(combined, null);

    m = serverList.expect("runTask");
    r = (Runnable) m.getAllParams()[0];
    r.run();

    methodNames = new String[3];
    methodNames[0] = "packetEncrypted";
    methodNames[1] = "packetEncrypted";
    methodNames[2] = "encryptedLinkEstablished";
    methods = serverList.expect(methodNames);

    b0 = (ByteBuffer) methods[0].getAllParams()[0];
    b1 = (ByteBuffer) methods[1].getAllParams()[0];
    total = b0.remaining() + b1.remaining();
    combined = ByteBuffer.allocate(total);
    combined.put(b0);
    combined.put(b1);
    helper.doneFillingBuffer(combined);

    clientEngine.feedEncryptedPacket(combined, null);

    clientList.expect("encryptedLinkEstablished");
  }