Merge pull request #11967 from jetty/fix/12.0.x/flakyCSLT

Fix flaky ContextScopeListenerTest
This commit is contained in:
Joakim Erdfelt 2024-06-27 11:50:43 -05:00 committed by GitHub
commit 32c1df6bd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 103 additions and 18 deletions

View File

@ -17,8 +17,8 @@ import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.DispatcherType;
@ -40,6 +40,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ContextScopeListenerTest
{
@ -72,7 +73,7 @@ public class ContextScopeListenerTest
}
@Test
public void testAsyncServlet() throws Exception
public void testAsyncServletAsyncBeforeDoGetExit() throws Exception
{
_contextHandler.addServlet(new ServletHolder(new HttpServlet()
{
@ -86,24 +87,33 @@ public class ContextScopeListenerTest
}
_history.add("doGet");
CountDownLatch latch = new CountDownLatch(1);
AsyncContext asyncContext = req.startAsync();
asyncContext.start(() ->
{
_history.add("asyncRunnable");
asyncContext.dispatch("/dispatch");
latch.countDown();
// wait until doGet call has exited
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> _history.get(_history.size() - 1).equals("exitScope /initialPath"));
});
try
{
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
}), "/");
_contextHandler.addEventListener(new ContextHandler.ContextScopeListener()
{
// Use a lock to prevent the async thread running the listener concurrently.
private final ReentrantLock _lock = new ReentrantLock();
@Override
public void enterScope(Context context, Request request)
{
_lock.lock();
String pathInContext = (request == null) ? "null" : Request.getPathInContext(request);
_history.add("enterScope " + pathInContext);
}
@ -113,19 +123,90 @@ public class ContextScopeListenerTest
{
String pathInContext = (request == null) ? "null" : Request.getPathInContext(request);
_history.add("exitScope " + pathInContext);
_lock.unlock();
}
});
URI uri = URI.create("http://localhost:" + _connector.getLocalPort() + "/initialPath");
ContentResponse response = _client.GET(uri);
assertThat(response.getStatus(), equalTo(HttpStatus.OK_200));
Awaitility.waitAtMost(5, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS).until(() -> _history.size() == 7);
assertHistory(
"enterScope /initialPath",
"doGet",
"enterScope /initialPath",
"asyncRunnable",
"asyncDispatch",
"exitScope /initialPath",
"exitScope /initialPath"
);
}
@Test
public void testAsyncServletAsyncAfterDoGetExit() throws Exception
{
_contextHandler.addServlet(new ServletHolder(new HttpServlet()
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
{
if (req.getDispatcherType() == DispatcherType.ASYNC)
{
_history.add("asyncDispatch");
return;
}
_history.add("doGet");
CountDownLatch latch = new CountDownLatch(1);
AsyncContext asyncContext = req.startAsync();
asyncContext.start(() ->
{
latch.countDown();
// wait until doGet call has exited
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> _history.get(_history.size() - 1).equals("exitScope /initialPath"));
_history.add("asyncRunnable");
asyncContext.dispatch("/dispatch");
});
try
{
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
}), "/");
_contextHandler.addEventListener(new ContextHandler.ContextScopeListener()
{
@Override
public void enterScope(Context context, Request request)
{
String pathInContext = (request == null) ? "null" : Request.getPathInContext(request);
_history.add("enterScope " + pathInContext);
}
@Override
public void exitScope(Context context, Request request)
{
String pathInContext = (request == null) ? "null" : Request.getPathInContext(request);
_history.add("exitScope " + pathInContext);
}
});
URI uri = URI.create("http://localhost:" + _connector.getLocalPort() + "/initialPath");
ContentResponse response = _client.GET(uri);
assertThat(response.getStatus(), equalTo(HttpStatus.OK_200));
Awaitility.waitAtMost(5, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS).until(() -> _history.size() == 9);
assertHistory(
"enterScope /initialPath",
"doGet",
"exitScope /initialPath",
"enterScope /initialPath",
"exitScope /initialPath",
"asyncRunnable",
"exitScope /initialPath",
"enterScope /initialPath",

View File

@ -17,7 +17,8 @@ import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.DispatcherType;
@ -37,6 +38,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ContextScopeListenerTest
{
@ -83,24 +85,31 @@ public class ContextScopeListenerTest
}
_history.add("doGet");
CountDownLatch latch = new CountDownLatch(1);
AsyncContext asyncContext = req.startAsync();
asyncContext.start(() ->
{
_history.add("asyncRunnable");
asyncContext.dispatch("/dispatch");
latch.countDown();
});
try
{
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
}), "/");
_contextHandler.addEventListener(new ContextHandler.ContextScopeListener()
{
// Use a lock to prevent the async thread running the listener concurrently.
private final ReentrantLock _lock = new ReentrantLock();
@Override
public void enterScope(ContextHandler.APIContext context, org.eclipse.jetty.ee9.nested.Request request, Object reason)
{
_lock.lock();
String pathInContext = (request == null) ? "null" : URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
_history.add("enterScope " + pathInContext);
}
@ -110,7 +119,6 @@ public class ContextScopeListenerTest
{
String pathInContext = (request == null) ? "null" : URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
_history.add("exitScope " + pathInContext);
_lock.unlock();
}
});
@ -120,14 +128,10 @@ public class ContextScopeListenerTest
assertHistory(
"enterScope /initialPath",
"doGet",
"exitScope /initialPath",
"enterScope /initialPath",
"asyncRunnable",
"exitScope /initialPath",
"enterScope /dispatch",
"asyncDispatch",
"exitScope /dispatch",
"enterScope /dispatch",
"exitScope /dispatch"
);
}