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

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


The following commit(s) were added to refs/heads/branch_10_0 by this push:
     new 6b54b4f0d9e SOLR-17935: Fix flaky TestRandomFlRTGCloud (#3860)
6b54b4f0d9e is described below

commit 6b54b4f0d9e077888cc332a89bf57b1eea10b75b
Author: Eric Pugh <[email protected]>
AuthorDate: Sat Nov 15 12:08:17 2025 -0500

    SOLR-17935: Fix flaky TestRandomFlRTGCloud (#3860)
    
    Rework the test TestRandomFlRTGCloud to avoid issues.   Change 
InputStreamResponseParser processRequest to correctly throw 
UnsupportedOperationException.
    
    ---------
    
    Co-authored-by: David Smiley <[email protected]>
---
 .../apache/solr/cloud/TestRandomFlRTGCloud.java    | 115 +++++++--------------
 .../solrj/impl/InputStreamResponseParser.java      |   9 +-
 .../response/InputStreamResponseParserTest.java    |  10 +-
 .../response/TestDelegationTokenResponse.java      |  18 +++-
 4 files changed, 61 insertions(+), 91 deletions(-)

diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java 
b/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java
index 8cd083c248a..3cf825f02bd 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java
@@ -17,7 +17,6 @@
 package org.apache.solr.cloud;
 
 import java.io.IOException;
-import java.io.StringReader;
 import java.lang.invoke.MethodHandles;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -37,12 +36,11 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.lucene.tests.util.TestUtil;
-import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.apache.HttpSolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.impl.InputStreamResponseParser;
+import org.apache.solr.client.solrj.impl.JsonMapResponseParser;
 import org.apache.solr.client.solrj.impl.XMLResponseParser;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
@@ -56,7 +54,6 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.Pair;
 import org.apache.solr.embedded.JettySolrRunner;
 import org.apache.solr.response.transform.DocTransformer;
 import org.apache.solr.response.transform.RawValueTransformerFactory;
@@ -80,8 +77,8 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase {
   /** A collection specific client for operations at the cloud level */
   private static CloudSolrClient COLLECTION_CLIENT;
 
-  /** We have a map of clients using specific writerTypes, keyed by pair of 
baseurl and wt */
-  private static final Map<Pair<String, String>, SolrClient> CLIENTS = new 
ConcurrentHashMap<>();
+  /** We have a map of clients, keyed by base URL */
+  private static final Map<String, SolrClient> CLIENTS = new 
ConcurrentHashMap<>();
 
   /** Always included in fl, so we can check what doc we're looking at */
   private static final FlValidator ID_VALIDATOR = new 
SimpleFieldValueValidator("id");
@@ -276,7 +273,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
     final float threshold = (float) itersSinceLastCommit / numIters;
     if (rand.nextFloat() < threshold) {
       log.info("COMMIT");
-      assertEquals(0, getRandomClient(rand).commit().getStatus());
+      assertEquals(0, 
cluster.getSolrClient(COLLECTION_NAME).commit().getStatus());
       return 0;
     }
     return itersSinceLastCommit + 1;
@@ -352,7 +349,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
     assertEquals(
         "Failed delete: " + Arrays.toString(docIds),
         0,
-        getRandomClient(random()).deleteById(ids).getStatus());
+        cluster.getSolrClient(COLLECTION_NAME).deleteById(ids).getStatus());
   }
 
   /**
@@ -361,7 +358,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
    */
   private SolrInputDocument addRandomDocument(final int docId)
       throws IOException, SolrServerException {
-    final SolrClient client = getRandomClient(random());
+    final SolrClient client = cluster.getSolrClient(COLLECTION_NAME);
 
     final SolrInputDocument doc =
         sdoc(
@@ -423,26 +420,8 @@ public class TestRandomFlRTGCloud extends 
SolrCloudTestCase {
     }
   }
 
-  private static final ResponseParser RAW_XML_RESPONSE_PARSER =
-      new InputStreamResponseParser("xml");
-  private static final ResponseParser RAW_JSON_RESPONSE_PARSER =
-      new InputStreamResponseParser("json");
-
-  /** Helper to convert from wt string parameter to actual SolrClient. */
-  private static SolrClient getSolrClient(final String jettyBaseUrl, final 
String wt) {
-    HttpSolrClient.Builder builder =
-        new 
HttpSolrClient.Builder(jettyBaseUrl).withDefaultCollection(COLLECTION_NAME);
-    switch (wt) {
-      case "xml":
-        builder.withResponseParser(RAW_XML_RESPONSE_PARSER);
-        break;
-      case "json":
-        builder.withResponseParser(RAW_JSON_RESPONSE_PARSER);
-        break;
-      default:
-        break;
-    }
-    return builder.build();
+  private static SolrClient getSolrClient(final String jettyBaseUrl) {
+    return new 
HttpSolrClient.Builder(jettyBaseUrl).withDefaultCollection(COLLECTION_NAME).build();
   }
 
   /**
@@ -508,7 +487,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
     }
 
     String wt = params.get(CommonParams.WT, "javabin");
-    final SolrClient client = getRandomClient(random(), wt);
+    final SolrClient client = getRandomClient(random());
 
     // If we have chosen a CloudSolrClient, then override wt parameter back to 
javabin format,
     // regardless of what was randomly picked.
@@ -516,30 +495,30 @@ public class TestRandomFlRTGCloud extends 
SolrCloudTestCase {
       wt = "javabin";
     }
 
-    final Object rsp;
-    final SolrDocumentList docs;
-    if ("javabin".equals(wt)) {
-      // the most common case
-      final QueryResponse qRsp = client.query(params);
-      assertNotNull(params.toString(), qRsp);
-      rsp = qRsp;
-      docs = getDocsFromRTGResponse(askForList, qRsp);
-    } else {
-      final NamedList<Object> nlRsp = client.request(new QueryRequest(params));
-      assertNotNull(params.toString(), nlRsp);
-      rsp = nlRsp;
-      final String textResult = 
InputStreamResponseParser.consumeResponseToString(nlRsp);
-      switch (wt) {
-        case "json":
-          docs = getDocsFromJsonResponse(askForList, textResult);
-          break;
-        case "xml":
-          docs = getDocsFromXmlResponse(askForList, textResult);
-          break;
-        default:
-          throw new IllegalStateException();
-      }
-    }
+    final Object rsp; // only here for an assertion message
+
+    var qr = new QueryRequest(params);
+    final SolrDocumentList docs =
+        switch (wt) {
+          case "javabin" -> { // the most common case
+            final QueryResponse qRsp = qr.process(client);
+            rsp = qRsp;
+            yield getDocsFromRTGResponse(askForList, qRsp);
+          }
+          case "json" -> {
+            qr.setResponseParser(new JsonMapResponseParser());
+            final NamedList<Object> nlRsp = client.request(qr);
+            rsp = nlRsp;
+            yield getDocsFromJsonResponse(askForList, nlRsp);
+          }
+          case "xml" -> {
+            qr.setResponseParser(new RawCapableXMLResponseParser());
+            final NamedList<Object> nlRsp = client.request(qr);
+            rsp = nlRsp;
+            yield getDocsFromXmlResponse(askForList, nlRsp);
+          }
+          default -> throw new IllegalStateException();
+        };
 
     assertNotNull(params + " => " + rsp, docs);
 
@@ -607,8 +586,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
 
   @SuppressWarnings("unchecked")
   private static SolrDocumentList getDocsFromJsonResponse(
-      final boolean expectList, final String rsp) throws IOException {
-    Map<String, Object> nl = (Map<String, Object>) ObjectBuilder.fromJSON(rsp);
+      final boolean expectList, final NamedList<?> nl) throws IOException {
     if (expectList) {
       return getSolrDocumentList((Map<String, Object>) nl.get("response"));
     } else {
@@ -621,29 +599,17 @@ public class TestRandomFlRTGCloud extends 
SolrCloudTestCase {
     }
   }
 
+  @SuppressWarnings("unchecked")
   private static SolrDocumentList getDocsFromXmlResponse(
-      final boolean expectList, final String rsp) {
-    return getDocsFromRTGResponse(
-        expectList,
-        new QueryResponse(
-            new RawCapableXMLResponseParser().processResponse(new 
StringReader(rsp))));
+      final boolean expectList, final NamedList<?> rsp) {
+    return getDocsFromRTGResponse(expectList, new 
QueryResponse((NamedList<Object>) rsp));
   }
 
   /**
-   * returns a random SolrClient -- either a CloudSolrClient, or an 
HttpSolrClient pointed at a node
-   * in our cluster. This method doesn't care which wt is defined.
+   * This method return a random SolrClient, and can include CloudSolrClient 
to choose from cloud in
+   * our cluster.
    */
   public static SolrClient getRandomClient(Random rand) {
-    List<String> writerTypes = List.of("javabin", "json", "xml");
-    int writerTypeIdx = TestUtil.nextInt(rand, 0, writerTypes.size() - 1);
-    return getRandomClient(rand, writerTypes.get(writerTypeIdx));
-  }
-
-  /**
-   * returns a random SolrClient -- either a CloudSolrClient, or an 
HttpSolrClient pointed at a node
-   * in our cluster. We have different CLIENTS created for each node based on 
their wt setting.
-   */
-  public static SolrClient getRandomClient(Random rand, String wt) {
     List<JettySolrRunner> jettySolrRunners = cluster.getJettySolrRunners();
     int numClients = jettySolrRunners.size();
     int idx = TestUtil.nextInt(rand, 0, numClients);
@@ -653,8 +619,7 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase 
{
     } else {
       JettySolrRunner jetty = jettySolrRunners.get(idx);
       String jettyBaseUrl = jetty.getBaseUrl().toString();
-      return CLIENTS.computeIfAbsent(
-          new Pair<>(jettyBaseUrl, wt), k -> getSolrClient(k.first(), 
k.second()));
+      return CLIENTS.computeIfAbsent(jettyBaseUrl, 
TestRandomFlRTGCloud::getSolrClient);
     }
   }
 
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/InputStreamResponseParser.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/InputStreamResponseParser.java
index 9da5117d046..ecf121e49b0 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/InputStreamResponseParser.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/InputStreamResponseParser.java
@@ -19,8 +19,6 @@ package org.apache.solr.client.solrj.impl;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.Set;
 import org.apache.solr.client.solrj.ResponseParser;
@@ -66,12 +64,7 @@ public class InputStreamResponseParser extends 
ResponseParser {
 
   @Override
   public NamedList<Object> processResponse(InputStream body, String encoding) 
throws IOException {
-    StringWriter writer = new StringWriter();
-    new InputStreamReader(body, encoding == null ? "UTF-8" : 
encoding).transferTo(writer);
-    String output = writer.toString();
-    NamedList<Object> list = new NamedList<>();
-    list.add("response", output);
-    return list;
+    throw new UnsupportedOperationException();
   }
 
   @Override
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java
index 4a39234d52d..f3e8433b85f 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java
@@ -95,11 +95,11 @@ public class InputStreamResponseParserTest extends 
SolrJettyTestBase {
     InputStreamResponseParser parser = new InputStreamResponseParser("xml");
     try (final InputStream is = getResponse()) {
       assertNotNull(is);
-      NamedList<Object> response = parser.processResponse(is, "UTF-8");
-
-      assertNotNull(response.get("response"));
-      String expectedResponse = new String(getResponse().readAllBytes(), 
StandardCharsets.UTF_8);
-      assertEquals(expectedResponse, response.get("response"));
+      assertThrows(
+          UnsupportedOperationException.class,
+          () -> {
+            parser.processResponse(is, "UTF-8");
+          });
     }
   }
 }
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestDelegationTokenResponse.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestDelegationTokenResponse.java
index eea00be5608..cd6c717a333 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestDelegationTokenResponse.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestDelegationTokenResponse.java
@@ -23,8 +23,10 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.solr.SolrTestCase;
 import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.client.solrj.impl.InputStreamResponseParser;
 import org.apache.solr.client.solrj.request.DelegationTokenRequest;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
 import org.junit.Test;
 import org.noggit.CharArr;
 import org.noggit.JSONWriter;
@@ -35,9 +37,19 @@ public class TestDelegationTokenResponse extends 
SolrTestCase {
       DelegationTokenRequest<?, ?> request, DelegationTokenResponse response, 
String responseBody)
       throws Exception {
     ResponseParser parser = request.getResponseParser();
-    response.setResponse(
-        parser.processResponse(
-            new 
ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), "UTF-8"));
+
+    // InputStreamResponseParser doesn't support processResponse(),
+    // so we need to handle it differently
+    if (parser instanceof InputStreamResponseParser) {
+      // For InputStreamResponseParser (used by Cancel request),
+      // create a NamedList directly since it expects empty response
+      response.setResponse(new NamedList<>());
+    } else {
+      // For JsonMapResponseParser (used by Get and Renew requests)
+      response.setResponse(
+          parser.processResponse(
+              new 
ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), "UTF-8"));
+    }
   }
 
   private String getNestedMapJson(String outerKey, String innerKey, Object 
innerValue) {

Reply via email to