blob: 5a404f3076021b4fc260075c5f732a0c2ba89b0c [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.EOFException;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.TimeoutException;
import javax.servlet.ReadListener;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ConcurrentArrayQueue;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AdvancedRunner.class)
public class HttpInputTest
{
Queue<String> _history = new ConcurrentArrayQueue<String>()
{
@Override
public boolean add(String s)
{
//System.err.println("history: "+s);
return super.add(s);
}
};
Queue<String> _fillAndParseSimulate = new ConcurrentArrayQueue<>();
HttpInput _in;
ReadListener _listener = new ReadListener()
{
@Override
public void onError(Throwable t)
{
_history.add("onError:"+t);
}
@Override
public void onDataAvailable() throws IOException
{
_history.add("onDataAvailable");
}
@Override
public void onAllDataRead() throws IOException
{
_history.add("onAllDataRead");
}
};
public class TContent extends HttpInput.Content
{
private final String _content;
public TContent(String content)
{
super(BufferUtil.toBuffer(content));
_content=content;
}
@Override
public void succeeded()
{
_history.add("Content succeeded "+_content);
super.succeeded();
}
@Override
public void failed(Throwable x)
{
_history.add("Content failed "+_content);
super.failed(x);
}
}
@Before
public void before()
{
_in=new HttpInput(new HttpChannelState(new HttpChannel(null,new HttpConfiguration(),null,null)
{
@Override
public void asyncReadFillInterested()
{
_history.add("asyncReadFillInterested");
}
})
{
@Override
public void onReadUnready()
{
_history.add("unready");
super.onReadUnready();
}
@Override
public boolean onReadPossible()
{
_history.add("onReadPossible");
return super.onReadPossible();
}
@Override
public boolean onReadReady()
{
_history.add("ready");
return super.onReadReady();
}
})
{
@Override
protected void produceContent() throws IOException
{
_history.add("produceContent "+_fillAndParseSimulate.size());
for (String s=_fillAndParseSimulate.poll();s!=null;s=_fillAndParseSimulate.poll())
{
if ("_EOF_".equals(s))
_in.eof();
else
_in.addContent(new TContent(s));
}
}
@Override
protected void blockForContent() throws IOException
{
_history.add("blockForContent");
super.blockForContent();
}
};
}
@After
public void after()
{
assertThat(_history.poll(),nullValue());
}
@Test
public void testEmpty() throws Exception
{
assertThat(_in.available(),equalTo(0));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.isReady(),equalTo(true));
assertThat(_history.poll(),nullValue());
}
@Test
public void testRead() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_fillAndParseSimulate.offer("EF");
_fillAndParseSimulate.offer("GH");
assertThat(_in.available(),equalTo(2));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.getContentConsumed(),equalTo(0L));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.getContentConsumed(),equalTo(1L));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_in.getContentConsumed(),equalTo(2L));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'C'));
assertThat(_in.read(),equalTo((int)'D'));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'E'));
assertThat(_in.read(),equalTo((int)'F'));
assertThat(_history.poll(),equalTo("produceContent 2"));
assertThat(_history.poll(),equalTo("Content succeeded EF"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'G'));
assertThat(_in.read(),equalTo((int)'H'));
assertThat(_history.poll(),equalTo("Content succeeded GH"));
assertThat(_history.poll(),nullValue());
assertThat(_in.getContentConsumed(),equalTo(8L));
assertThat(_history.poll(),nullValue());
}
@Test
public void testReRead() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_fillAndParseSimulate.offer("EF");
_fillAndParseSimulate.offer("GH");
assertThat(_in.available(),equalTo(2));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.getContentConsumed(),equalTo(0L));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.getContentConsumed(),equalTo(1L));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_in.getContentConsumed(),equalTo(2L));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'C'));
assertThat(_in.read(),equalTo((int)'D'));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'E'));
_in.prependContent(new HttpInput.Content(BufferUtil.toBuffer("abcde")));
assertThat(_in.available(),equalTo(5));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.getContentConsumed(),equalTo(0L));
assertThat(_in.read(),equalTo((int)'a'));
assertThat(_in.getContentConsumed(),equalTo(1L));
assertThat(_in.read(),equalTo((int)'b'));
assertThat(_in.getContentConsumed(),equalTo(2L));
assertThat(_in.read(),equalTo((int)'c'));
assertThat(_in.read(),equalTo((int)'d'));
assertThat(_in.read(),equalTo((int)'e'));
assertThat(_in.read(),equalTo((int)'F'));
assertThat(_history.poll(),equalTo("produceContent 2"));
assertThat(_history.poll(),equalTo("Content succeeded EF"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'G'));
assertThat(_in.read(),equalTo((int)'H'));
assertThat(_history.poll(),equalTo("Content succeeded GH"));
assertThat(_history.poll(),nullValue());
assertThat(_in.getContentConsumed(),equalTo(8L));
assertThat(_history.poll(),nullValue());
}
@Test
public void testBlockingRead() throws Exception
{
new Thread()
{
public void run()
{
try
{
Thread.sleep(500);
_in.addContent(new TContent("AB"));
}
catch(Throwable th)
{
th.printStackTrace();
}
}
}.start();
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("blockForContent"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testReadEOF() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_in.eof();
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.available(),equalTo(2));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'C'));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo((int)'D'));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo(-1));
assertThat(_in.isFinished(),equalTo(true));
assertThat(_history.poll(),nullValue());
}
@Test
public void testReadEarlyEOF() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_in.earlyEOF();
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.available(),equalTo(2));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_in.read(),equalTo((int)'C'));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo((int)'D'));
try
{
_in.read();
fail();
}
catch(EOFException eof)
{
assertThat(_in.isFinished(),equalTo(true));
}
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testBlockingEOF() throws Exception
{
new Thread()
{
public void run()
{
try
{
Thread.sleep(500);
_in.eof();
}
catch(Throwable th)
{
th.printStackTrace();
}
}
}.start();
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo(-1));
assertThat(_in.isFinished(),equalTo(true));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("blockForContent"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testAsyncEmpty() throws Exception
{
_in.setReadListener(_listener);
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testAsyncRead() throws Exception
{
_in.setReadListener(_listener);
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.addContent(new TContent("AB"));
_fillAndParseSimulate.add("CD");
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(true));
assertThat(_history.poll(),equalTo("produceContent 1"));
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo((int)'C'));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.read(),equalTo((int)'D'));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testAsyncEOF() throws Exception
{
_in.setReadListener(_listener);
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
_in.eof();
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.isFinished(),equalTo(false));
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
assertThat(_in.read(),equalTo(-1));
assertThat(_in.isFinished(),equalTo(true));
assertThat(_history.poll(),equalTo("ready"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testAsyncReadEOF() throws Exception
{
_in.setReadListener(_listener);
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.addContent(new TContent("AB"));
_fillAndParseSimulate.add("_EOF_");
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.read(),equalTo((int)'A'));
assertThat(_in.isReady(),equalTo(true));
assertThat(_in.read(),equalTo((int)'B'));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.isReady(),equalTo(true));
assertThat(_history.poll(),equalTo("produceContent 1"));
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isFinished(),equalTo(false));
assertThat(_in.read(),equalTo(-1));
assertThat(_in.isFinished(),equalTo(true));
assertThat(_history.poll(),equalTo("ready"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(true));
assertThat(_history.poll(),nullValue());
}
@Test
public void testAsyncError() throws Exception
{
_in.setReadListener(_listener);
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_history.poll(),equalTo("onDataAvailable"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(false));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),equalTo("unready"));
assertThat(_history.poll(),nullValue());
_in.failed(new TimeoutException());
assertThat(_history.poll(),equalTo("onReadPossible"));
assertThat(_history.poll(),nullValue());
_in.run();
assertThat(_in.isFinished(),equalTo(true));
assertThat(_history.poll(),equalTo("onError:java.util.concurrent.TimeoutException"));
assertThat(_history.poll(),nullValue());
assertThat(_in.isReady(),equalTo(true));
try
{
_in.read();
fail();
}
catch(IOException e)
{
assertThat(e.getCause(),Matchers.instanceOf(TimeoutException.class));
assertThat(_in.isFinished(),equalTo(true));
}
assertThat(_history.poll(),nullValue());
}
@Test
public void testRecycle() throws Exception
{
testAsyncRead();
_in.recycle();
testAsyncRead();
_in.recycle();
testReadEOF();
}
@Test
public void testConsumeAll() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_fillAndParseSimulate.offer("EF");
_fillAndParseSimulate.offer("GH");
assertThat(_in.read(),equalTo((int)'A'));
assertFalse(_in.consumeAll());
assertThat(_in.getContentConsumed(),equalTo(8L));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),equalTo("produceContent 2"));
assertThat(_history.poll(),equalTo("Content succeeded EF"));
assertThat(_history.poll(),equalTo("Content succeeded GH"));
assertThat(_history.poll(),equalTo("produceContent 0"));
assertThat(_history.poll(),nullValue());
}
@Test
public void testConsumeAllEOF() throws Exception
{
_in.addContent(new TContent("AB"));
_in.addContent(new TContent("CD"));
_fillAndParseSimulate.offer("EF");
_fillAndParseSimulate.offer("GH");
_fillAndParseSimulate.offer("_EOF_");
assertThat(_in.read(),equalTo((int)'A'));
assertTrue(_in.consumeAll());
assertThat(_in.getContentConsumed(),equalTo(8L));
assertThat(_history.poll(),equalTo("Content succeeded AB"));
assertThat(_history.poll(),equalTo("Content succeeded CD"));
assertThat(_history.poll(),equalTo("produceContent 3"));
assertThat(_history.poll(),equalTo("Content succeeded EF"));
assertThat(_history.poll(),equalTo("Content succeeded GH"));
assertThat(_history.poll(),nullValue());
}
}