Merge pull request #11967 from jetty/fix/12.0.x/flakyCSLT
Fix flaky ContextScopeListenerTest
This commit is contained in:
commit
32c1df6bd2
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue