This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch branch_10_1 in repository https://gitbox.apache.org/repos/asf/solr.git
commit 6c9a9df55f4db8a99aec34cf89b29c40799d32f1 Author: Eric Pugh <[email protected]> AuthorDate: Sun Sep 27 18:32:33 2026 -0400 Centralize the CloudSolrClient mock setup used by CrossDC tests (#4823) (cherry picked from commit 0d2a4649c79a404e9f4aa1bfe26b88c3bb37407c) (cherry picked from commit 7bf403f3e1527585d06a34c04bdc375462f941ea) --- .../solr/crossdc/manager/CrossDcMockUtils.java | 41 ++++++++++++++ .../manager/consumer/KafkaCrossDcConsumerTest.java | 6 +-- .../messageprocessor/SolrMessageProcessorTest.java | 7 ++- .../messageprocessor/TestMessageProcessor.java | 62 ++-------------------- 4 files changed, 50 insertions(+), 66 deletions(-) diff --git a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/CrossDcMockUtils.java b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/CrossDcMockUtils.java new file mode 100644 index 00000000000..729afc12d12 --- /dev/null +++ b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/CrossDcMockUtils.java @@ -0,0 +1,41 @@ +/* + * 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.crossdc.manager; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.ClusterStateProvider; + +/** Shared Mockito helper for tests that mock a {@link CloudSolrClient}. */ +public final class CrossDcMockUtils { + + private CrossDcMockUtils() {} + + /** + * Mocks a client with a mocked cluster-state provider. {@code SolrMessageProcessor} reads the + * live-node list from this provider before processing a request. Tests can retrieve the provider + * with {@link CloudSolrClient#getClusterStateProvider()} to stub or verify it. + */ + public static CloudSolrClient mockCloudSolrClientWithClusterStateProvider() { + CloudSolrClient client = mock(CloudSolrClient.class); + when(client.getClusterStateProvider()).thenReturn(mock(ClusterStateProvider.class)); + return client; + } +} diff --git a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/KafkaCrossDcConsumerTest.java b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/KafkaCrossDcConsumerTest.java index 3ce4a2b42d3..1a33060ddc6 100644 --- a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/KafkaCrossDcConsumerTest.java +++ b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/consumer/KafkaCrossDcConsumerTest.java @@ -61,6 +61,7 @@ import org.apache.solr.crossdc.common.IQueueHandler; import org.apache.solr.crossdc.common.KafkaCrossDcConf; import org.apache.solr.crossdc.common.KafkaMirroringSink; import org.apache.solr.crossdc.common.MirroredSolrRequest; +import org.apache.solr.crossdc.manager.CrossDcMockUtils; import org.apache.solr.crossdc.manager.messageprocessor.SolrMessageProcessor; import org.junit.After; import org.junit.Before; @@ -91,10 +92,9 @@ public class KafkaCrossDcConsumerTest { @Before public void setUp() { kafkaConsumerMock = mock(KafkaConsumer.class); - clusterStateProviderMock = mock(ClusterStateProvider.class); + solrClientMock = CrossDcMockUtils.mockCloudSolrClientWithClusterStateProvider(); + clusterStateProviderMock = solrClientMock.getClusterStateProvider(); doAnswer(inv -> clusterStateProviderIsClosed).when(clusterStateProviderMock).isClosed(); - solrClientMock = mock(CloudSolrClient.class); - doReturn(clusterStateProviderMock).when(solrClientMock).getClusterStateProvider(); kafkaMirroringSinkMock = mock(KafkaMirroringSink.class); messageProcessorMock = mock(SolrMessageProcessor.class); conf = testCrossDCConf(); diff --git a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/SolrMessageProcessorTest.java b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/SolrMessageProcessorTest.java index 39f3d43acd8..73348254b39 100644 --- a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/SolrMessageProcessorTest.java +++ b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/SolrMessageProcessorTest.java @@ -37,6 +37,7 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.crossdc.common.IQueueHandler; import org.apache.solr.crossdc.common.MirroredSolrRequest; import org.apache.solr.crossdc.common.ResubmitBackoffPolicy; +import org.apache.solr.crossdc.manager.CrossDcMockUtils; import org.apache.solr.crossdc.manager.consumer.OtelMetrics; import org.junit.Before; import org.junit.BeforeClass; @@ -56,10 +57,8 @@ public class SolrMessageProcessorTest { @Before public void setUp() { - client = mock(CloudSolrClient.class); - // handleItem() probes the cluster through the state provider, so the mock must supply one - clusterStateProvider = mock(ClusterStateProvider.class); - when(client.getClusterStateProvider()).thenReturn(clusterStateProvider); + client = CrossDcMockUtils.mockCloudSolrClientWithClusterStateProvider(); + clusterStateProvider = client.getClusterStateProvider(); resubmitBackoffPolicy = mock(ResubmitBackoffPolicy.class); solrMessageProcessor = new SolrMessageProcessor(mock(OtelMetrics.class), () -> client, resubmitBackoffPolicy); diff --git a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/TestMessageProcessor.java b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/TestMessageProcessor.java index f7a82d2cd5b..00845e5cd07 100644 --- a/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/TestMessageProcessor.java +++ b/solr/cross-dc-manager/src/test/org/apache/solr/crossdc/manager/messageprocessor/TestMessageProcessor.java @@ -18,7 +18,6 @@ package org.apache.solr.crossdc.manager.messageprocessor; import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyString; @@ -28,34 +27,26 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.util.Map; import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.impl.ClusterStateProvider; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.response.UpdateResponse; import org.apache.solr.common.SolrException; -import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.util.NamedList; import org.apache.solr.crossdc.common.IQueueHandler; import org.apache.solr.crossdc.common.MirroredSolrRequest; import org.apache.solr.crossdc.common.ResubmitBackoffPolicy; +import org.apache.solr.crossdc.manager.CrossDcMockUtils; import org.apache.solr.crossdc.manager.consumer.ConsumerMetrics; import org.apache.solr.crossdc.manager.consumer.OtelMetrics; -import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; public class TestMessageProcessor { - static final String VERSION_FIELD = "_version_"; - - @Mock private CloudSolrClient solrClient; + private CloudSolrClient solrClient; private SolrMessageProcessor processor; - private AutoCloseable mocks; private final ResubmitBackoffPolicy backoffPolicy = spy( @@ -73,60 +64,13 @@ public class TestMessageProcessor { @Before public void setUp() { - mocks = MockitoAnnotations.openMocks(this); - - // handleItem() probes the cluster through the state provider, so the mock must supply one - ClusterStateProvider clusterStateProvider = Mockito.mock(ClusterStateProvider.class); - when(solrClient.getClusterStateProvider()).thenReturn(clusterStateProvider); + solrClient = CrossDcMockUtils.mockCloudSolrClientWithClusterStateProvider(); ConsumerMetrics metrics = Mockito.mock(OtelMetrics.class); processor = Mockito.spy(new SolrMessageProcessor(metrics, () -> solrClient, backoffPolicy)); Mockito.doNothing().when(processor).uncheckedSleep(anyLong()); } - @After - public void tearDown() throws Exception { - if (mocks != null) { - mocks.close(); - } - } - - @Test - public void testDocumentSanitization() { - UpdateRequest request = spy(new UpdateRequest()); - - // Add docs with and without version - SolrInputDocument doc1 = new SolrInputDocument(); - doc1.setField("id", 1); - doc1.setField(VERSION_FIELD, 1); - request.add(doc1); - SolrInputDocument doc2 = new SolrInputDocument(); - doc2.setField("id", 2); - request.add(doc2); - - // Delete by id with and without version - request.deleteById("1"); - request.deleteById("2", 10L); - - request.setParam("shouldMirror", "true"); - // The response is irrelevant, but it will fail because mocked server returns null when - // processing - processor.handleItem(new MirroredSolrRequest<>(request)); - - // After processing, check that all version fields are stripped - for (SolrInputDocument doc : request.getDocuments()) { - assertNull("Doc still has version", doc.getField(VERSION_FIELD)); - } - - // Check versions in delete by id - for (Map<String, Object> idParams : request.getDeleteByIdMap().values()) { - if (idParams != null) { - idParams.put(UpdateRequest.VER, null); - assertNull("Delete still has version", idParams.get(UpdateRequest.VER)); - } - } - } - @Test @Ignore // needs to be modified to fully support request.process public void testSuccessNoBackoff() throws Exception {
