private void testSpdyEcho(int version) throws Throwable {
    ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor));
    ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor));

    ChannelBuffer frames = createFrames(version);

    EchoHandler sh = new EchoHandler(frames, true);
    EchoHandler ch = new EchoHandler(frames, false);

    sb.getPipeline().addLast("decoder", new SpdyFrameDecoder(version));
    sb.getPipeline().addLast("encoder", new SpdyFrameEncoder(version));
    sb.getPipeline().addLast("handler", sh);

    cb.getPipeline().addLast("handler", ch);

    Channel sc = sb.bind(new InetSocketAddress(0));
    int port = ((InetSocketAddress) sc.getLocalAddress()).getPort();

    ChannelFuture ccf = cb.connect(new InetSocketAddress(InetAddress.getLocalHost(), port));
    assertTrue(ccf.awaitUninterruptibly().isSuccess());

    Channel cc = ccf.getChannel();
    cc.write(frames);

    while (ch.counter < frames.writerIndex() - ignoredBytes) {
      if (sh.exception.get() != null) {
        break;
      }
      if (ch.exception.get() != null) {
        break;
      }

      try {
        Thread.sleep(1);
      } catch (InterruptedException e) {
        // Ignore.
      }
    }

    sh.channel.close().awaitUninterruptibly();
    ch.channel.close().awaitUninterruptibly();
    sc.close().awaitUninterruptibly();

    if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) {
      throw sh.exception.get();
    }
    if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) {
      throw ch.exception.get();
    }
    if (sh.exception.get() != null) {
      throw sh.exception.get();
    }
    if (ch.exception.get() != null) {
      throw ch.exception.get();
    }
  }
  @Test
  public void testShutdownTime() throws Throwable {
    ServerSocketChannel serverSocket = ServerSocketChannel.open();
    serverSocket.socket().bind(new InetSocketAddress(0));

    ClientBootstrap b =
        new ClientBootstrap(
            new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
    b.getPipeline().addLast("handler", new DummyHandler());

    long startTime;
    long stopTime;

    try {
      serverSocket.configureBlocking(false);

      ChannelFuture f =
          b.connect(
              new InetSocketAddress(
                  SocketAddresses.LOCALHOST, serverSocket.socket().getLocalPort()));

      serverSocket.accept();
      f.awaitUninterruptibly();

      if (f.getCause() != null) {
        throw f.getCause();
      }
      assertTrue(f.isSuccess());

      startTime = System.currentTimeMillis();

      f.getChannel().close().awaitUninterruptibly();
    } finally {
      b.getFactory().releaseExternalResources();

      stopTime = System.currentTimeMillis();

      try {
        serverSocket.close();
      } catch (IOException ex) {
        // Ignore.
      }
    }

    long shutdownTime = stopTime - startTime;
    assertTrue("Shutdown takes too long: " + shutdownTime + " ms", shutdownTime < 500);
  }