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:
Simone Bordet 2020-09-02 10:00:57 +02:00 committed by GitHub
commit 4e8bf3723c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 57 deletions

View File

@ -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;
} }
} }

View File

@ -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));