Merge pull request #5216 from eclipse/jetty-9.4.x-3974-flaky-asyncmiddlemanservlet-test-overflow
Issue #3974 flaky AsyncMiddleManServletTest overflow to filesystem tests
This commit is contained in:
commit
4e8bf3723c
|
@ -185,7 +185,7 @@ public class AsyncMiddleManServlet extends AbstractProxyServlet
|
||||||
}
|
}
|
||||||
catch (Throwable x)
|
catch (Throwable x)
|
||||||
{
|
{
|
||||||
_log.info("Exception while transforming " + transformer, x);
|
_log.info("Exception while transforming {} ", transformer, x);
|
||||||
throw x;
|
throw x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.ThreadInfo;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -38,6 +41,7 @@ import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
@ -100,9 +104,9 @@ public class AsyncMiddleManServletTest
|
||||||
private HttpClient client;
|
private HttpClient client;
|
||||||
private Server proxy;
|
private Server proxy;
|
||||||
private ServerConnector proxyConnector;
|
private ServerConnector proxyConnector;
|
||||||
|
private AsyncMiddleManServlet proxyServlet;
|
||||||
private Server server;
|
private Server server;
|
||||||
private ServerConnector serverConnector;
|
private ServerConnector serverConnector;
|
||||||
private StacklessLogging stackless;
|
|
||||||
|
|
||||||
private void startServer(HttpServlet servlet) throws Exception
|
private void startServer(HttpServlet servlet) throws Exception
|
||||||
{
|
{
|
||||||
|
@ -140,13 +144,12 @@ public class AsyncMiddleManServletTest
|
||||||
proxy.addConnector(proxyConnector);
|
proxy.addConnector(proxyConnector);
|
||||||
|
|
||||||
ServletContextHandler proxyContext = new ServletContextHandler(proxy, "/", true, false);
|
ServletContextHandler proxyContext = new ServletContextHandler(proxy, "/", true, false);
|
||||||
|
this.proxyServlet = proxyServlet;
|
||||||
ServletHolder proxyServletHolder = new ServletHolder(proxyServlet);
|
ServletHolder proxyServletHolder = new ServletHolder(proxyServlet);
|
||||||
proxyServletHolder.setInitParameters(initParams);
|
proxyServletHolder.setInitParameters(initParams);
|
||||||
proxyContext.addServlet(proxyServletHolder, "/*");
|
proxyContext.addServlet(proxyServletHolder, "/*");
|
||||||
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
stackless = new StacklessLogging(proxyServlet._log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startClient() throws Exception
|
private void startClient() throws Exception
|
||||||
|
@ -165,7 +168,6 @@ public class AsyncMiddleManServletTest
|
||||||
client.stop();
|
client.stop();
|
||||||
proxy.stop();
|
proxy.stop();
|
||||||
server.stop();
|
server.stop();
|
||||||
stackless.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -511,43 +513,46 @@ public class AsyncMiddleManServletTest
|
||||||
});
|
});
|
||||||
startClient();
|
startClient();
|
||||||
|
|
||||||
byte[] bytes = new byte[1024];
|
try (StacklessLogging ignored = new StacklessLogging(proxyServlet._log))
|
||||||
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
{
|
||||||
.content(new BytesContentProvider(bytes))
|
byte[] bytes = new byte[1024];
|
||||||
.timeout(5, TimeUnit.SECONDS)
|
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
.send();
|
.content(new BytesContentProvider(bytes))
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
assertEquals(500, response.getStatus());
|
assertEquals(500, response.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpstreamTransformationThrowsAfterCommittingProxyRequest() throws Exception
|
public void testUpstreamTransformationThrowsAfterCommittingProxyRequest() throws Exception
|
||||||
{
|
{
|
||||||
try (StacklessLogging ignored = new StacklessLogging(HttpChannel.class))
|
startServer(new EchoHttpServlet());
|
||||||
|
startProxy(new AsyncMiddleManServlet()
|
||||||
{
|
{
|
||||||
startServer(new EchoHttpServlet());
|
@Override
|
||||||
startProxy(new AsyncMiddleManServlet()
|
protected ContentTransformer newClientRequestContentTransformer(HttpServletRequest clientRequest, Request proxyRequest)
|
||||||
{
|
{
|
||||||
@Override
|
return new ContentTransformer()
|
||||||
protected ContentTransformer newClientRequestContentTransformer(HttpServletRequest clientRequest, Request proxyRequest)
|
|
||||||
{
|
{
|
||||||
return new ContentTransformer()
|
private int count;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(ByteBuffer input, boolean finished, List<ByteBuffer> output)
|
||||||
{
|
{
|
||||||
private int count;
|
if (++count < 2)
|
||||||
|
output.add(input);
|
||||||
@Override
|
else
|
||||||
public void transform(ByteBuffer input, boolean finished, List<ByteBuffer> output)
|
throw new NullPointerException("explicitly_thrown_by_test");
|
||||||
{
|
}
|
||||||
if (++count < 2)
|
};
|
||||||
output.add(input);
|
}
|
||||||
else
|
});
|
||||||
throw new NullPointerException("explicitly_thrown_by_test");
|
startClient();
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
startClient();
|
|
||||||
|
|
||||||
|
try (StacklessLogging ignored = new StacklessLogging(proxyServlet._log))
|
||||||
|
{
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
DeferredContentProvider content = new DeferredContentProvider();
|
DeferredContentProvider content = new DeferredContentProvider();
|
||||||
client.newRequest("localhost", serverConnector.getLocalPort())
|
client.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
|
@ -628,11 +633,14 @@ public class AsyncMiddleManServletTest
|
||||||
});
|
});
|
||||||
startClient();
|
startClient();
|
||||||
|
|
||||||
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
try (StacklessLogging ignored = new StacklessLogging(proxyServlet._log))
|
||||||
.timeout(5, TimeUnit.SECONDS)
|
{
|
||||||
.send();
|
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
assertEquals(502, response.getStatus());
|
assertEquals(502, response.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1037,31 +1045,70 @@ public class AsyncMiddleManServletTest
|
||||||
});
|
});
|
||||||
startClient();
|
startClient();
|
||||||
|
|
||||||
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
try
|
||||||
.timeout(5, TimeUnit.SECONDS)
|
|
||||||
.send();
|
|
||||||
|
|
||||||
assertEquals(200, response.getStatus());
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> obj = (Map<String, Object>)JSON.parse(response.getContentAsString());
|
|
||||||
assertNotNull(obj);
|
|
||||||
assertEquals(2, obj.size());
|
|
||||||
assertEquals(value0, obj.get(key0));
|
|
||||||
assertEquals(value1, obj.get(key2));
|
|
||||||
// Make sure the files do not exist.
|
|
||||||
try (DirectoryStream<Path> paths = Files.newDirectoryStream(targetTestsDir, inputPrefix + "*.*"))
|
|
||||||
{
|
{
|
||||||
assertFalse(paths.iterator().hasNext());
|
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
}
|
.timeout(15, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
// File deletion is delayed on windows, testing for deletion is not going to work
|
assertEquals(200, response.getStatus());
|
||||||
if (!OS.WINDOWS.isCurrentOs())
|
@SuppressWarnings("unchecked")
|
||||||
{
|
Map<String, Object> obj = (Map<String, Object>)JSON.parse(response.getContentAsString());
|
||||||
try (DirectoryStream<Path> paths = Files.newDirectoryStream(targetTestsDir, outputPrefix + "*.*"))
|
assertNotNull(obj);
|
||||||
|
assertEquals(2, obj.size());
|
||||||
|
assertEquals(value0, obj.get(key0));
|
||||||
|
assertEquals(value1, obj.get(key2));
|
||||||
|
|
||||||
|
// File deletion is delayed on windows, testing for deletion is not going to work
|
||||||
|
if (!OS.WINDOWS.isCurrentOs())
|
||||||
{
|
{
|
||||||
assertFalse(paths.iterator().hasNext());
|
try (DirectoryStream<Path> paths = Files.newDirectoryStream(targetTestsDir, outputPrefix + "*.*"))
|
||||||
|
{
|
||||||
|
assertFalse(paths.iterator().hasNext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
LOG.warn("Client Dump");
|
||||||
|
QueuedThreadPool qtp = (QueuedThreadPool)client.getExecutor();
|
||||||
|
qtp.setDetailedDump(true);
|
||||||
|
client.dumpStdErr();
|
||||||
|
LOG.warn("Server Dump");
|
||||||
|
qtp = (QueuedThreadPool)server.getThreadPool();
|
||||||
|
qtp.setDetailedDump(true);
|
||||||
|
server.dumpStdErr();
|
||||||
|
LOG.warn("Thread Dump");
|
||||||
|
System.err.println(generateThreadDump());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateThreadDump()
|
||||||
|
{
|
||||||
|
StringBuilder dump = new StringBuilder();
|
||||||
|
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
||||||
|
for (ThreadInfo thread : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 400))
|
||||||
|
{
|
||||||
|
dump.append('"').append(thread.getThreadName()).append("\" ");
|
||||||
|
dump.append(" #").append(thread.getThreadId());
|
||||||
|
dump.append("\n java.lang.Thread.State: ");
|
||||||
|
Thread.State state = thread.getThreadState();
|
||||||
|
dump.append(state.name());
|
||||||
|
if (state == Thread.State.BLOCKED || state == Thread.State.WAITING || state == Thread.State.TIMED_WAITING)
|
||||||
|
{
|
||||||
|
dump.append(" (locked on ");
|
||||||
|
dump.append(thread.getLockInfo());
|
||||||
|
dump.append(')');
|
||||||
|
}
|
||||||
|
for (StackTraceElement stackTraceElement : thread.getStackTrace())
|
||||||
|
{
|
||||||
|
dump.append("\n\tat ");
|
||||||
|
dump.append(stackTraceElement);
|
||||||
|
}
|
||||||
|
dump.append("\n\n");
|
||||||
|
}
|
||||||
|
return dump.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1122,7 +1169,7 @@ public class AsyncMiddleManServletTest
|
||||||
return data.length + 1;
|
return data.length + 1;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.timeout(5 * idleTimeout, TimeUnit.MILLISECONDS)
|
.timeout(15 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
assertTrue(destroyLatch.await(5 * idleTimeout, TimeUnit.MILLISECONDS));
|
assertTrue(destroyLatch.await(5 * idleTimeout, TimeUnit.MILLISECONDS));
|
||||||
|
@ -1182,7 +1229,7 @@ public class AsyncMiddleManServletTest
|
||||||
startClient();
|
startClient();
|
||||||
|
|
||||||
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
.timeout(5, TimeUnit.SECONDS)
|
.timeout(15, TimeUnit.SECONDS)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
assertTrue(serviceLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(serviceLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
|
Loading…
Reference in New Issue