This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch branch_10_0
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 95cb7ff348c26b3bf2fd4bd2f5ee4b35fe5b2fa5
Author: David Smiley <[email protected]>
AuthorDate: Thu Nov 20 09:11:39 2025 -0500

    Tests: ServletFixtures (#3877)
    
    Deduplicate DebugServlet into one; resolve some semantic differences 
regarding case sensitivity of headers.  Put several test servlets under a 
ServletFixtures class.
---
 .../client/solrj/impl/BasicHttpSolrClientTest.java | 225 ++++----------------
 .../solr/client/solrj/impl/DebugServlet.java       | 180 ----------------
 .../impl/Http2SolrClientCompatibilityTest.java     |   1 +
 .../client/solrj/impl/Http2SolrClientTest.java     |   3 +-
 .../client/solrj/impl/HttpJdkSolrClientTest.java   |   1 +
 .../client/solrj/impl/HttpSolrClientTestBase.java  |  15 +-
 .../solr/client/solrj/impl/ServletFixtures.java    | 228 +++++++++++++++++++++
 7 files changed, 281 insertions(+), 372 deletions(-)

diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
index 601c2442c10..ef372e93e50 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
@@ -16,26 +16,17 @@
  */
 package org.apache.solr.client.solrj.impl;
 
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
 import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpException;
@@ -64,6 +55,10 @@ import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.apache.HttpClientUtil;
 import org.apache.solr.client.solrj.apache.HttpSolrClient;
 import org.apache.solr.client.solrj.apache.SolrPortAwareCookieSpecFactory;
+import org.apache.solr.client.solrj.impl.ServletFixtures.DebugServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.RedirectServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.SlowServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.SlowStreamServlet;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -73,7 +68,6 @@ import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SuppressForbidden;
 import org.apache.solr.embedded.JettyConfig;
 import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.junit.BeforeClass;
@@ -86,141 +80,6 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private static final String UA_VERSION = SolrVersion.LATEST_STRING;
 
-  public static class RedirectServlet extends HttpServlet {
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      resp.sendRedirect("/solr/collection1/select?" + req.getQueryString());
-    }
-  }
-
-  public static class SlowServlet extends HttpServlet {
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      try {
-        Thread.sleep(5000);
-      } catch (InterruptedException ignored) {
-      }
-    }
-  }
-
-  public static class SlowStreamServlet extends HttpServlet {
-
-    public static final int PACKET_MS = 500;
-
-    @Override
-    @SuppressForbidden(reason = "don't forbid in tests")
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-      String countStr = req.getParameter("count");
-      IntStream.range(0, countStr == null ? 10 : Integer.parseInt(countStr))
-          .forEach(
-              i -> {
-                try {
-                  Thread.sleep(PACKET_MS);
-                  
resp.getOutputStream().write(String.valueOf(i).getBytes(StandardCharsets.UTF_8));
-                  resp.getOutputStream().flush();
-                } catch (IOException | InterruptedException e) {
-                  throw new RuntimeException(e);
-                }
-              });
-    }
-  }
-
-  public static class DebugServlet extends HttpServlet {
-    public static void clear() {
-      lastMethod = null;
-      headers = null;
-      parameters = null;
-      errorCode = null;
-      queryString = null;
-      cookies = null;
-    }
-
-    public static Integer errorCode = null;
-    public static String lastMethod = null;
-    public static HashMap<String, String> headers = null;
-    public static Map<String, String[]> parameters = null;
-    public static String queryString = null;
-    public static jakarta.servlet.http.Cookie[] cookies = null;
-
-    public static void setErrorCode(Integer code) {
-      errorCode = code;
-    }
-
-    @Override
-    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      lastMethod = "delete";
-      recordRequest(req, resp);
-    }
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      lastMethod = "get";
-      recordRequest(req, resp);
-    }
-
-    @Override
-    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      lastMethod = "head";
-      recordRequest(req, resp);
-    }
-
-    private void setHeaders(HttpServletRequest req) {
-      Enumeration<String> headerNames = req.getHeaderNames();
-      headers = new HashMap<>();
-      while (headerNames.hasMoreElements()) {
-        final String name = headerNames.nextElement();
-        headers.put(name, req.getHeader(name));
-      }
-    }
-
-    @SuppressForbidden(reason = "fake servlet only")
-    private void setParameters(HttpServletRequest req) {
-      parameters = req.getParameterMap();
-    }
-
-    private void setQueryString(HttpServletRequest req) {
-      queryString = req.getQueryString();
-    }
-
-    private void setCookies(HttpServletRequest req) {
-      jakarta.servlet.http.Cookie[] ck = req.getCookies();
-      cookies = req.getCookies();
-    }
-
-    @Override
-    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      lastMethod = "post";
-      recordRequest(req, resp);
-    }
-
-    @Override
-    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-      lastMethod = "put";
-      recordRequest(req, resp);
-    }
-
-    private void recordRequest(HttpServletRequest req, HttpServletResponse 
resp) {
-      setHeaders(req);
-      setParameters(req);
-      setQueryString(req);
-      setCookies(req);
-      if (null != errorCode) {
-        try {
-          resp.sendError(errorCode);
-        } catch (IOException e) {
-          throw new RuntimeException("sendError IO fail in DebugServlet", e);
-        }
-      }
-    }
-  }
-
   @BeforeClass
   public static void beforeTest() throws Exception {
     JettyConfig jettyConfig =
@@ -290,18 +149,18 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       // agent
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       // default wt
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
       // agent
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       // keepalive
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
       // content-type
-      assertNull(DebugServlet.headers.get("Content-Type"));
+      assertNull(DebugServlet.headers.get("content-type"));
       // param encoding
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
@@ -314,18 +173,18 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("post", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
       assertEquals(
           "application/x-www-form-urlencoded; charset=UTF-8",
-          DebugServlet.headers.get("Content-Type"));
+          DebugServlet.headers.get("content-type"));
 
       // PUT
       DebugServlet.clear();
@@ -335,18 +194,18 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("put", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
       assertEquals(
           "application/x-www-form-urlencoded; charset=UTF-8",
-          DebugServlet.headers.get("Content-Type"));
+          DebugServlet.headers.get("content-type"));
     }
 
     // XML
@@ -362,15 +221,15 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("get", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("xml", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
 
       // XML/POST
       DebugServlet.clear();
@@ -380,18 +239,18 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("post", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("xml", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
       assertEquals(
           "application/x-www-form-urlencoded; charset=UTF-8",
-          DebugServlet.headers.get("Content-Type"));
+          DebugServlet.headers.get("content-type"));
 
       DebugServlet.clear();
       queryRequest.setMethod(METHOD.PUT);
@@ -400,18 +259,18 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("put", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("xml", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
       assertEquals(
           "application/x-www-form-urlencoded; charset=UTF-8",
-          DebugServlet.headers.get("Content-Type"));
+          DebugServlet.headers.get("content-type"));
     }
   }
 
@@ -431,16 +290,16 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       // agent
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       // default wt
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
       // agent
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       // keepalive
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
     }
 
     // XML
@@ -458,13 +317,13 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("post", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("xml", DebugServlet.parameters.get(CommonParams.WT)[0]);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
-      assertEquals("keep-alive", DebugServlet.headers.get("Connection"));
+          DebugServlet.headers.get("user-agent"));
+      assertEquals("keep-alive", DebugServlet.headers.get("connection"));
     }
   }
 
@@ -497,12 +356,12 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       // agent
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       // default wt
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
       // content type
-      assertEquals("application/javabin", 
DebugServlet.headers.get("Content-Type"));
+      assertEquals("application/javabin", 
DebugServlet.headers.get("content-type"));
       // parameter encoding
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
@@ -524,10 +383,10 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("post", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("xml", DebugServlet.parameters.get(CommonParams.WT)[0]);
-      assertEquals("application/xml; charset=UTF-8", 
DebugServlet.headers.get("Content-Type"));
+      assertEquals("application/xml; charset=UTF-8", 
DebugServlet.headers.get("content-type"));
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
     }
@@ -548,10 +407,10 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       assertEquals("post", DebugServlet.lastMethod);
       assertEquals(
           "Solr[" + HttpSolrClient.class.getName() + "] " + UA_VERSION,
-          DebugServlet.headers.get("User-Agent"));
+          DebugServlet.headers.get("user-agent"));
       assertEquals(1, DebugServlet.parameters.get(CommonParams.WT).length);
       assertEquals("javabin", DebugServlet.parameters.get(CommonParams.WT)[0]);
-      assertEquals("application/javabin", 
DebugServlet.headers.get("Content-Type"));
+      assertEquals("application/javabin", 
DebugServlet.headers.get("content-type"));
       assertEquals(1, DebugServlet.parameters.get("a").length);
       assertEquals("\u1234", DebugServlet.parameters.get("a")[0]);
     }
@@ -597,7 +456,7 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       // verify request header gets set
       DebugServlet.clear();
       expectThrows(SolrClient.RemoteSolrException.class, () -> 
queryRequest.process(client));
-      assertNull(DebugServlet.headers.toString(), 
DebugServlet.headers.get("Accept-Encoding"));
+      assertNull(DebugServlet.headers.toString(), 
DebugServlet.headers.get("accept-encoding"));
     }
 
     try (SolrClient client =
@@ -606,7 +465,7 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
         queryRequest.process(client);
       } catch (SolrClient.RemoteSolrException ignored) {
       }
-      assertNotNull(DebugServlet.headers.get("Accept-Encoding"));
+      assertNotNull(DebugServlet.headers.get("accept-encoding"));
     }
 
     try (SolrClient client =
@@ -616,7 +475,7 @@ public class BasicHttpSolrClientTest extends 
SolrJettyTestBase {
       } catch (SolrClient.RemoteSolrException ignored) {
       }
     }
-    assertNull(DebugServlet.headers.get("Accept-Encoding"));
+    assertNull(DebugServlet.headers.get("accept-encoding"));
 
     // verify server compresses output
     HttpGet get = new HttpGet(getCoreUrl() + "/select?q=foo&wt=xml");
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/DebugServlet.java 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/DebugServlet.java
deleted file mode 100644
index dee9b4a2549..00000000000
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/DebugServlet.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.client.solrj.impl;
-
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import org.apache.solr.common.util.SuppressForbidden;
-
-public class DebugServlet extends HttpServlet {
-  public static void clear() {
-    lastMethod = null;
-    url = null;
-    headers = null;
-    parameters = null;
-    errorCode = null;
-    queryString = null;
-    cookies = null;
-    responseHeaders = null;
-    responseBodyByQueryFragment = new ConcurrentHashMap<>();
-  }
-
-  public static Integer errorCode = null;
-  public static String lastMethod = null;
-  public static String url = null;
-  public static HashMap<String, String> headers = null;
-  public static Map<String, String[]> parameters = null;
-  public static String queryString = null;
-  public static Cookie[] cookies = null;
-  public static List<String[]> responseHeaders = null;
-  public static Map<String, Object> responseBodyByQueryFragment = new 
ConcurrentHashMap<>();
-  public static byte[] requestBody = null;
-
-  public static void setErrorCode(Integer code) {
-    errorCode = code;
-  }
-
-  public static void addResponseHeader(String headerName, String headerValue) {
-    if (responseHeaders == null) {
-      responseHeaders = new ArrayList<>();
-    }
-    responseHeaders.add(new String[] {headerName, headerValue});
-  }
-
-  @Override
-  protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
-      throws ServletException, IOException {
-    lastMethod = "delete";
-    recordRequest(req, resp);
-  }
-
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-      throws ServletException, IOException {
-    lastMethod = "get";
-    recordRequest(req, resp);
-  }
-
-  @Override
-  protected void doHead(HttpServletRequest req, HttpServletResponse resp)
-      throws ServletException, IOException {
-    lastMethod = "head";
-    recordRequest(req, resp);
-  }
-
-  private void setHeaders(HttpServletRequest req) {
-    Enumeration<String> headerNames = req.getHeaderNames();
-    headers = new HashMap<>();
-    while (headerNames.hasMoreElements()) {
-      final String name = headerNames.nextElement();
-      headers.put(name.toLowerCase(Locale.getDefault()), req.getHeader(name));
-    }
-  }
-
-  @SuppressForbidden(reason = "fake servlet only")
-  private void setParameters(HttpServletRequest req) {
-    parameters = req.getParameterMap();
-  }
-
-  private void setQueryString(HttpServletRequest req) {
-    queryString = req.getQueryString();
-  }
-
-  private void setCookies(HttpServletRequest req) {
-    Cookie[] ck = req.getCookies();
-    cookies = req.getCookies();
-  }
-
-  @Override
-  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
-      throws ServletException, IOException {
-    lastMethod = "post";
-    recordRequest(req, resp);
-  }
-
-  @Override
-  protected void doPut(HttpServletRequest req, HttpServletResponse resp)
-      throws ServletException, IOException {
-    lastMethod = "put";
-    recordRequest(req, resp);
-  }
-
-  @SuppressForbidden(reason = "tests needn't comply")
-  private void recordRequest(HttpServletRequest req, HttpServletResponse resp) 
{
-    url = req.getRequestURL().toString();
-    setHeaders(req);
-    setParameters(req);
-    setQueryString(req);
-    setCookies(req);
-    try {
-      requestBody = req.getInputStream().readAllBytes();
-    } catch (Exception e) {
-      // ignore
-    }
-    if (responseHeaders != null) {
-      for (String[] h : responseHeaders) {
-        resp.addHeader(h[0], h[1]);
-      }
-    }
-    String qs = req.getQueryString();
-    qs = qs == null ? "" : qs;
-    Object responseBody = null;
-
-    // Tests can set this up to return different response bodies based on 
substrings in the query
-    // string
-    for (Map.Entry<String, Object> entry : 
responseBodyByQueryFragment.entrySet()) {
-      if (qs.contains(entry.getKey())) {
-        responseBody = entry.getValue();
-        break;
-      }
-    }
-
-    if (responseBody != null) {
-      try {
-        if (responseBody instanceof String) {
-          resp.getWriter().print((String) responseBody);
-        } else if (responseBody instanceof byte[]) {
-          resp.getOutputStream().write((byte[]) responseBody);
-        } else {
-          throw new IllegalArgumentException(
-              "Only String and byte[] are supported for responseBody.");
-        }
-      } catch (IOException ioe) {
-        throw new RuntimeException(ioe);
-      }
-    }
-    if (null != errorCode) {
-      try {
-        resp.sendError(errorCode);
-      } catch (IOException e) {
-        throw new RuntimeException("sendError IO fail in DebugServlet", e);
-      }
-    }
-  }
-}
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientCompatibilityTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientCompatibilityTest.java
index 3763e251da6..e58a016f9b6 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientCompatibilityTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientCompatibilityTest.java
@@ -23,6 +23,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.ServletFixtures.DebugServlet;
 import org.apache.solr.embedded.JettyConfig;
 import org.apache.solr.util.LogLevel;
 import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
index 92d089f5ad2..b05da93f3f3 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java
@@ -35,6 +35,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.ServletFixtures.DebugServlet;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.SolrPing;
 import org.apache.solr.common.SolrException;
@@ -675,7 +676,7 @@ public class Http2SolrClientTest extends 
HttpSolrClientTestBase {
 
       // too little time to succeed
       int packets = LuceneTestCase.RANDOM_MULTIPLIER == 1 ? 10 : 80; // 60 
crosses a default timeout
-      long timeToSendMs = (long) packets * 
BasicHttpSolrClientTest.SlowStreamServlet.PACKET_MS;
+      long timeToSendMs = (long) packets * 
ServletFixtures.SlowStreamServlet.PACKET_MS;
       QueryRequest req = new QueryRequest(SolrParams.of("count", "" + 
packets));
       req.setResponseParser(new InputStreamResponseParser(FILE_STREAM));
       assertIsTimeout(expectThrows(SolrServerException.class, () -> 
oldClient.request(req)));
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java
index 8616cca08e9..b29be52e5f2 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java
@@ -37,6 +37,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.ServletFixtures.DebugServlet;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.SolrPingResponse;
 import org.apache.solr.common.params.CommonParams;
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientTestBase.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientTestBase.java
index 79266ac9024..6a870b2b58e 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientTestBase.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientTestBase.java
@@ -42,6 +42,10 @@ import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.apache.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.ServletFixtures.DebugServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.RedirectServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.SlowServlet;
+import org.apache.solr.client.solrj.impl.ServletFixtures.SlowStreamServlet;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -74,15 +78,10 @@ public abstract class HttpSolrClientTestBase extends 
SolrJettyTestBase {
   public static void beforeTest() throws Exception {
     JettyConfig jettyConfig =
         JettyConfig.builder()
-            .withServlet(
-                new 
ServletHolder(BasicHttpSolrClientTest.RedirectServlet.class),
-                REDIRECT_SERVLET_REGEX)
-            .withServlet(
-                new ServletHolder(BasicHttpSolrClientTest.SlowServlet.class), 
SLOW_SERVLET_REGEX)
+            .withServlet(new ServletHolder(RedirectServlet.class), 
REDIRECT_SERVLET_REGEX)
+            .withServlet(new ServletHolder(SlowServlet.class), 
SLOW_SERVLET_REGEX)
             .withServlet(new ServletHolder(DebugServlet.class), 
DEBUG_SERVLET_REGEX)
-            .withServlet(
-                new 
ServletHolder(BasicHttpSolrClientTest.SlowStreamServlet.class),
-                SLOW_STREAM_SERVLET_REGEX)
+            .withServlet(new ServletHolder(SlowStreamServlet.class), 
SLOW_STREAM_SERVLET_REGEX)
             .withSSLConfig(sslConfig.buildServerSSLConfig())
             .build();
     createAndStartJetty(legacyExampleCollection1SolrHome(), jettyConfig);
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ServletFixtures.java 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ServletFixtures.java
new file mode 100644
index 00000000000..c093cd673ca
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ServletFixtures.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.impl;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.IntStream;
+import org.apache.solr.common.util.SuppressForbidden;
+
+public class ServletFixtures {
+
+  private ServletFixtures() {}
+
+  public static class RedirectServlet extends HttpServlet {
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      resp.sendRedirect("/solr/collection1/select?" + req.getQueryString());
+    }
+  }
+
+  public static class SlowServlet extends HttpServlet {
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      try {
+        Thread.sleep(5000);
+      } catch (InterruptedException ignored) {
+      }
+    }
+  }
+
+  public static class SlowStreamServlet extends HttpServlet {
+
+    public static final int PACKET_MS = 500;
+
+    @SuppressForbidden(reason = "forbiddenApis: getParameter is fine in tests")
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
+      String countStr = req.getParameter("count");
+      IntStream.range(0, countStr == null ? 10 : Integer.parseInt(countStr))
+          .forEach(
+              i -> {
+                try {
+                  Thread.sleep(PACKET_MS);
+                  
resp.getOutputStream().write(String.valueOf(i).getBytes(StandardCharsets.UTF_8));
+                  resp.getOutputStream().flush();
+                } catch (IOException | InterruptedException e) {
+                  throw new RuntimeException(e);
+                }
+              });
+    }
+  }
+
+  public static class DebugServlet extends HttpServlet {
+    public static void clear() {
+      lastMethod = null;
+      url = null;
+      headers = null;
+      parameters = null;
+      errorCode = null;
+      queryString = null;
+      cookies = null;
+      responseHeaders = null;
+      responseBodyByQueryFragment = new ConcurrentHashMap<>();
+    }
+
+    public static Integer errorCode = null;
+    public static String lastMethod = null;
+    public static String url = null;
+    public static HashMap<String, String> headers = null; // lowercase keys!
+    public static Map<String, String[]> parameters = null;
+    public static String queryString = null;
+    public static Cookie[] cookies = null;
+    public static List<String[]> responseHeaders = null;
+    public static Map<String, Object> responseBodyByQueryFragment = new 
ConcurrentHashMap<>();
+    public static byte[] requestBody = null;
+
+    public static void setErrorCode(Integer code) {
+      errorCode = code;
+    }
+
+    public static void addResponseHeader(String headerName, String 
headerValue) {
+      if (responseHeaders == null) {
+        responseHeaders = new ArrayList<>();
+      }
+      responseHeaders.add(new String[] {headerName, headerValue});
+    }
+
+    @Override
+    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      lastMethod = "delete";
+      recordRequest(req, resp);
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      lastMethod = "get";
+      recordRequest(req, resp);
+    }
+
+    @Override
+    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      lastMethod = "head";
+      recordRequest(req, resp);
+    }
+
+    private void setHeaders(HttpServletRequest req) {
+      Enumeration<String> headerNames = req.getHeaderNames();
+      headers = new HashMap<>();
+      while (headerNames.hasMoreElements()) {
+        final String name = headerNames.nextElement();
+        headers.put(name.toLowerCase(Locale.ROOT), req.getHeader(name));
+      }
+    }
+
+    @SuppressForbidden(reason = "fake servlet only")
+    private void setParameters(HttpServletRequest req) {
+      parameters = req.getParameterMap();
+    }
+
+    private void setQueryString(HttpServletRequest req) {
+      queryString = req.getQueryString();
+    }
+
+    private void setCookies(HttpServletRequest req) {
+      Cookie[] ck = req.getCookies();
+      cookies = req.getCookies();
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      lastMethod = "post";
+      recordRequest(req, resp);
+    }
+
+    @Override
+    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+      lastMethod = "put";
+      recordRequest(req, resp);
+    }
+
+    @SuppressForbidden(reason = "forbiddenApis: getWriter is fine in tests")
+    private void recordRequest(HttpServletRequest req, HttpServletResponse 
resp) {
+      url = req.getRequestURL().toString();
+      setHeaders(req);
+      setParameters(req);
+      setQueryString(req);
+      setCookies(req);
+      try {
+        requestBody = req.getInputStream().readAllBytes();
+      } catch (Exception e) {
+        // ignore
+      }
+      if (responseHeaders != null) {
+        for (String[] h : responseHeaders) {
+          resp.addHeader(h[0], h[1]);
+        }
+      }
+      String qs = req.getQueryString();
+      qs = qs == null ? "" : qs;
+      Object responseBody = null;
+
+      // Tests can set this up to return different response bodies based on 
substrings in the query
+      // string
+      for (Map.Entry<String, Object> entry : 
responseBodyByQueryFragment.entrySet()) {
+        if (qs.contains(entry.getKey())) {
+          responseBody = entry.getValue();
+          break;
+        }
+      }
+
+      if (responseBody != null) {
+        try {
+          if (responseBody instanceof String) {
+            resp.getWriter().print((String) responseBody);
+          } else if (responseBody instanceof byte[]) {
+            resp.getOutputStream().write((byte[]) responseBody);
+          } else {
+            throw new IllegalArgumentException(
+                "Only String and byte[] are supported for responseBody.");
+          }
+        } catch (IOException ioe) {
+          throw new RuntimeException(ioe);
+        }
+      }
+      if (null != errorCode) {
+        try {
+          resp.sendError(errorCode);
+        } catch (IOException e) {
+          throw new RuntimeException("sendError IO fail in DebugServlet", e);
+        }
+      }
+    }
+  }
+}


Reply via email to