@Test
  public void testGenerateParseOneByteAtATime() throws Exception {
    byte flags = SettingsInfo.CLEAR_PERSISTED;
    Settings settings = new Settings();
    settings.put(new Settings.Setting(Settings.ID.DOWNLOAD_RETRANSMISSION_RATE, 100));
    settings.put(new Settings.Setting(Settings.ID.ROUND_TRIP_TIME, 500));
    SettingsFrame frame1 = new SettingsFrame(SPDY.V2, flags, settings);
    Generator generator =
        new Generator(new MappedByteBufferPool(), new StandardCompressionFactory().newCompressor());
    ByteBuffer buffer = generator.control(frame1);

    Assert.assertNotNull(buffer);

    TestSPDYParserListener listener = new TestSPDYParserListener();
    Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
    parser.addListener(listener);
    while (buffer.hasRemaining()) parser.parse(ByteBuffer.wrap(new byte[] {buffer.get()}));
    ControlFrame frame2 = listener.getControlFrame();

    Assert.assertNotNull(frame2);
    Assert.assertEquals(ControlFrameType.SETTINGS, frame2.getType());
    SettingsFrame settingsFrame = (SettingsFrame) frame2;
    Assert.assertEquals(SPDY.V2, settingsFrame.getVersion());
    Assert.assertEquals(flags, settingsFrame.getFlags());
    Assert.assertEquals(settings, settingsFrame.getSettings());
  }
  @Test
  public void testGenerateParse() throws Exception {
    byte flags = SettingsInfo.CLEAR_PERSISTED;
    Settings settings = new Settings();
    settings.put(
        new Settings.Setting(Settings.ID.MAX_CONCURRENT_STREAMS, Settings.Flag.PERSIST, 100));
    settings.put(new Settings.Setting(Settings.ID.ROUND_TRIP_TIME, Settings.Flag.PERSISTED, 500));
    SettingsFrame frame1 = new SettingsFrame(SPDY.V2, flags, settings);
    Generator generator =
        new Generator(new MappedByteBufferPool(), new StandardCompressionFactory().newCompressor());
    ByteBuffer buffer = generator.control(frame1);

    Assert.assertNotNull(buffer);

    TestSPDYParserListener listener = new TestSPDYParserListener();
    Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
    parser.addListener(listener);
    parser.parse(buffer);
    ControlFrame frame2 = listener.getControlFrame();

    Assert.assertNotNull(frame2);
    Assert.assertEquals(ControlFrameType.SETTINGS, frame2.getType());
    SettingsFrame settingsFrame = (SettingsFrame) frame2;
    Assert.assertEquals(SPDY.V2, settingsFrame.getVersion());
    Assert.assertEquals(flags, settingsFrame.getFlags());
    Assert.assertEquals(settings, settingsFrame.getSettings());
  }
  private void generateAndEnqueueControlFrame(
      IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Callback callback) {
    try {
      // Synchronization is necessary, since we may have concurrent replies
      // and those needs to be generated and enqueued atomically in order
      // to maintain a correct compression context
      synchronized (this) {
        ByteBuffer buffer = generator.control(frame);
        LOG.debug("Queuing {} on {}", frame, stream);
        ControlFrameBytes frameBytes = new ControlFrameBytes(stream, callback, frame, buffer);
        if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);

        // Special handling for PING frames, they must be sent as soon as possible
        if (ControlFrameType.PING == frame.getType()) prepend(frameBytes);
        else append(frameBytes);
      }
    } catch (Exception x) {
      notifyCallbackFailed(callback, x);
    }
  }