public void testClientFlowControlOneBigWrite() throws Exception
{
final int windowSize = 1536;
final Exchanger<DataInfo> exchanger = new Exchanger<>();
final CountDownLatch settingsLatch = new CountDownLatch(1);
Session session = startClient(SPDY.V3, startServer(SPDY.V3, new ServerSessionFrameListener.Adapter()
{
@Override
public void onConnect(Session session)
{
Settings settings = new Settings();
settings.put(new Settings.Setting(Settings.ID.INITIAL_WINDOW_SIZE, windowSize));
session.settings(new SettingsInfo(settings), new FutureCallback());
}
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
private AtomicInteger dataFrames = new AtomicInteger();
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
try
{
int dataFrames = this.dataFrames.incrementAndGet();
if (dataFrames == 1)
{
// Do not consume nor read from the data frame.
// We should then be flow-control stalled
exchanger.exchange(dataInfo);
}
else if (dataFrames == 2)
{
// Read but not consume, we should be flow-control stalled
dataInfo.asByteBuffer(false);
exchanger.exchange(dataInfo);
}
else if (dataFrames == 3)
{
// Consume partially, we should be flow-control stalled
dataInfo.consumeInto(ByteBuffer.allocate(dataInfo.length() / 2));
exchanger.exchange(dataInfo);
}
else if (dataFrames == 4 || dataFrames == 5)
{
// Consume totally
dataInfo.asByteBuffer(true);
exchanger.exchange(dataInfo);
}
else
{
Assert.fail();
}
}
catch (InterruptedException x)
{
throw new SPDYException(x);
}
}
};
}
}), new SessionFrameListener.Adapter()
{
@Override
public void onSettings(Session session, SettingsInfo settingsInfo)
{
settingsLatch.countDown();
}
});
Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
final int length = 5 * windowSize;
stream.data(new BytesDataInfo(new byte[length], true), new Callback.Adapter());
DataInfo dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
checkThatWeAreFlowControlStalled(exchanger);