You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by mk...@apache.org on 2024/02/27 13:27:53 UTC

(solr) branch branch_9x updated: SOLR-17156: introducing RandomNoReverseMergePolicyFactory (#2289) (#2305)

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

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


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 6783d260ed5 SOLR-17156: introducing RandomNoReverseMergePolicyFactory (#2289) (#2305)
6783d260ed5 is described below

commit 6783d260ed5f5ffe60d3dc31a129d185481e8bfb
Author: Mikhail Khludnev <mk...@users.noreply.github.com>
AuthorDate: Tue Feb 27 16:27:46 2024 +0300

    SOLR-17156: introducing RandomNoReverseMergePolicyFactory (#2289) (#2305)
    
    - Defend other block join tests from reverse merge.
    
     - introduce @ClassRule for no revers merge policy
---
 .../solr/cloud/NestedShardedAtomicUpdateTest.java  |  6 +++
 .../org/apache/solr/handler/JsonLoaderTest.java    |  6 +++
 .../transform/TestChildDocTransformer.java         |  6 +++
 .../TestChildDocTransformerHierarchy.java          |  6 +++
 .../facet/TestJsonFacetsWithNestedObjects.java     |  6 +++
 .../org/apache/solr/search/join/BJQParserTest.java |  6 +++
 .../solr/search/join/TestCloudNestedDocsSort.java  |  8 +++-
 .../solr/search/join/TestNestedDocsSort.java       |  6 +++
 .../join/another/BJQFilterAccessibleTest.java      |  6 +++
 .../org/apache/solr/update/AddBlockUpdateTest.java |  6 +++
 .../test/org/apache/solr/update/RootFieldTest.java |  7 +++
 .../solr/update/TestNestedUpdateProcessor.java     |  6 +++
 .../solr/update/processor/AtomicUpdatesTest.java   |  6 +++
 .../update/processor/NestedAtomicUpdateTest.java   |  6 +++
 .../org/apache/solr/util/RandomMergePolicy.java    | 11 +++++
 .../util/RandomNoReverseMergePolicyFactory.java    | 53 ++++++++++++++++++++++
 16 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java b/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
index fb94304f897..8aaeda4779a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/NestedShardedAtomicUpdateTest.java
@@ -35,9 +35,12 @@ import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.Replica;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class NestedShardedAtomicUpdateTest extends SolrCloudTestCase {
   private static final String DEBUG_LABEL = MethodHandles.lookup().lookupClass().getName();
@@ -46,6 +49,9 @@ public class NestedShardedAtomicUpdateTest extends SolrCloudTestCase {
   private static CloudSolrClient cloudClient;
   private static List<SolrClient> clients; // not CloudSolrClient
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     final String configName = DEBUG_LABEL + "_config-set";
diff --git a/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java b/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
index f0be036bf9d..41ca734d01f 100644
--- a/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/JsonLoaderTest.java
@@ -35,11 +35,17 @@ import org.apache.solr.update.AddUpdateCommand;
 import org.apache.solr.update.CommitUpdateCommand;
 import org.apache.solr.update.DeleteUpdateCommand;
 import org.apache.solr.update.processor.BufferingRequestProcessor;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class JsonLoaderTest extends SolrTestCaseJ4 {
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeTests() throws Exception {
     initCore("solrconfig.xml", "schema.xml");
diff --git a/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformer.java b/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformer.java
index d330f30c393..d24e726ba9b 100644
--- a/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformer.java
+++ b/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformer.java
@@ -27,16 +27,22 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.BasicResultContext;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.hamcrest.MatcherAssert;
 import org.junit.After;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestChildDocTransformer extends SolrTestCaseJ4 {
 
   private static String ID_FIELD = "id";
   private String[] titleVals = new String[2];
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml", "schema-root.xml"); // *not* the "nest" schema
diff --git a/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformerHierarchy.java b/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformerHierarchy.java
index 9f99dd7aba7..8a84e9420b1 100644
--- a/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformerHierarchy.java
+++ b/solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformerHierarchy.java
@@ -29,10 +29,13 @@ import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.BasicResultContext;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
 
@@ -49,6 +52,9 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
   // multiple segments.
   private static final String fqToExcludeNonTestedDocs = "{!frange l=0}id_i";
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig-minimal.xml", "schema-nest.xml"); // use "nest" schema
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetsWithNestedObjects.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetsWithNestedObjects.java
index b57fc84cf9b..439b8c3224d 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetsWithNestedObjects.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetsWithNestedObjects.java
@@ -19,11 +19,17 @@ package org.apache.solr.search.facet;
 import org.apache.solr.SolrTestCaseHS;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestJsonFacetsWithNestedObjects extends SolrTestCaseHS {
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeTests() throws Exception {
     initCore("solrconfig-tlog.xml", "schema_latest.xml");
diff --git a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
index 2282f33e1b0..5fcb7455187 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
@@ -37,9 +37,12 @@ import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.SyntaxError;
 import org.apache.solr.util.BaseTestHarness;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.After;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class BJQParserTest extends SolrTestCaseJ4 {
 
@@ -47,6 +50,9 @@ public class BJQParserTest extends SolrTestCaseJ4 {
   private static final List<String> xyz = Arrays.asList("x", "y", "z");
   private static final String[] abcdef = new String[] {"a", "b", "c", "d", "e", "f"};
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml", "schema15.xml");
diff --git a/solr/core/src/test/org/apache/solr/search/join/TestCloudNestedDocsSort.java b/solr/core/src/test/org/apache/solr/search/join/TestCloudNestedDocsSort.java
index bd2501b0a11..2c0cea7e18b 100644
--- a/solr/core/src/test/org/apache/solr/search/join/TestCloudNestedDocsSort.java
+++ b/solr/core/src/test/org/apache/solr/search/join/TestCloudNestedDocsSort.java
@@ -35,18 +35,24 @@ import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.util.IOUtils;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestCloudNestedDocsSort extends SolrCloudTestCase {
 
-  private static ArrayList<String> vals = new ArrayList<>();
+  private static final ArrayList<String> vals = new ArrayList<>();
   private static CloudSolrClient client;
   private static int maxDocs;
   private static String matchingParent;
   private static String matchingChild;
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void setupCluster() throws Exception {
     final int numVals = atLeast(10);
diff --git a/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java b/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
index 904af50fe7d..00c58558527 100644
--- a/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
+++ b/solr/core/src/test/org/apache/solr/search/join/TestNestedDocsSort.java
@@ -25,11 +25,17 @@ import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.SolrCache;
 import org.apache.solr.search.SortSpec;
 import org.apache.solr.search.SortSpecParsing;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestNestedDocsSort extends SolrTestCaseJ4 {
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml", "schema.xml");
diff --git a/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java b/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java
index 680e8be971a..973bfee6c69 100644
--- a/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/another/BJQFilterAccessibleTest.java
@@ -29,10 +29,16 @@ import org.apache.lucene.search.join.ToParentBlockJoinQuery;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.join.BlockJoinParentQParser;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.rules.TestRule;
 
 public class BJQFilterAccessibleTest extends SolrTestCaseJ4 {
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml", "schema15.xml");
diff --git a/solr/core/src/test/org/apache/solr/update/AddBlockUpdateTest.java b/solr/core/src/test/org/apache/solr/update/AddBlockUpdateTest.java
index 3a205f42839..9dc7666bfbe 100644
--- a/solr/core/src/test/org/apache/solr/update/AddBlockUpdateTest.java
+++ b/solr/core/src/test/org/apache/solr/update/AddBlockUpdateTest.java
@@ -66,13 +66,16 @@ import org.apache.solr.handler.loader.XMLLoader;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.apache.solr.util.RefCounted;
 import org.hamcrest.MatcherAssert;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -96,6 +99,9 @@ public class AddBlockUpdateTest extends SolrTestCaseJ4 {
   private RefCounted<SolrIndexSearcher> searcherRef;
   private SolrIndexSearcher _searcher;
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     String oldCacheNamePropValue = System.getProperty("blockJoinParentFilterCache");
diff --git a/solr/core/src/test/org/apache/solr/update/RootFieldTest.java b/solr/core/src/test/org/apache/solr/update/RootFieldTest.java
index 12cb5f6b35a..8529bb88c99 100644
--- a/solr/core/src/test/org/apache/solr/update/RootFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/update/RootFieldTest.java
@@ -29,9 +29,12 @@ import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.hamcrest.MatcherAssert;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class RootFieldTest extends EmbeddedSolrServerTestBase {
   private static boolean useRootSchema;
@@ -43,6 +46,10 @@ public class RootFieldTest extends EmbeddedSolrServerTestBase {
     return useRootSchema;
   }
 
+  // not necessary right now but will be once block logic is asserted
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeTest() throws Exception {
     solrClientTestRule.startSolr(Path.of(SolrTestCaseJ4.TEST_HOME()));
diff --git a/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java b/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
index f8eaf7b47ca..c2c080d7a0e 100644
--- a/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
+++ b/solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java
@@ -34,10 +34,13 @@ import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.update.processor.NestedUpdateProcessorFactory;
 import org.apache.solr.update.processor.UpdateRequestProcessor;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.hamcrest.MatcherAssert;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
 
@@ -102,6 +105,9 @@ public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
           + "    }\n"
           + "}";
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig-minimal.xml", "schema-nest.xml");
diff --git a/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java b/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
index ef81af271a9..36ba8f9ca61 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
@@ -27,14 +27,20 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.util.DateMathParser;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.hamcrest.MatcherAssert;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class AtomicUpdatesTest extends SolrTestCaseJ4 {
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeTests() throws Exception {
     System.setProperty("enable.update.log", "true");
diff --git a/solr/core/src/test/org/apache/solr/update/processor/NestedAtomicUpdateTest.java b/solr/core/src/test/org/apache/solr/update/processor/NestedAtomicUpdateTest.java
index c8d11232809..01852b9d8fd 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/NestedAtomicUpdateTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/NestedAtomicUpdateTest.java
@@ -36,14 +36,20 @@ import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.SolrInputField;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.component.RealTimeGetComponent;
+import org.apache.solr.util.RandomNoReverseMergePolicyFactory;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 public class NestedAtomicUpdateTest extends SolrTestCaseJ4 {
 
   private static final String VERSION = "_version_";
 
+  @ClassRule
+  public static final TestRule noReverseMerge = RandomNoReverseMergePolicyFactory.createRule();
+
   @BeforeClass
   public static void beforeTests() throws Exception {
     initCore("solrconfig-tlog.xml", "schema-nest.xml"); // use "nest" schema
diff --git a/solr/test-framework/src/java/org/apache/solr/util/RandomMergePolicy.java b/solr/test-framework/src/java/org/apache/solr/util/RandomMergePolicy.java
index e1d2a61d3fd..58d3a7ab2f1 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/RandomMergePolicy.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/RandomMergePolicy.java
@@ -19,6 +19,7 @@ package org.apache.solr.util;
 import java.lang.invoke.MethodHandles;
 import org.apache.lucene.index.FilterMergePolicy;
 import org.apache.lucene.index.MergePolicy;
+import org.apache.lucene.tests.index.MockRandomMergePolicy;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,6 +37,16 @@ public class RandomMergePolicy extends FilterMergePolicy {
     this(LuceneTestCase.newMergePolicy());
   }
 
+  /**
+   * Creates an instance.
+   *
+   * @param allowMockMP whether to give a chance to return {@linkplain MockRandomMergePolicy}, which
+   *     may reverse docs in the segment
+   */
+  public RandomMergePolicy(boolean allowMockMP) {
+    this(LuceneTestCase.newMergePolicy(LuceneTestCase.random(), allowMockMP));
+  }
+
   protected RandomMergePolicy(MergePolicy inner) {
     super(inner);
     if (log.isInfoEnabled()) {
diff --git a/solr/test-framework/src/java/org/apache/solr/util/RandomNoReverseMergePolicyFactory.java b/solr/test-framework/src/java/org/apache/solr/util/RandomNoReverseMergePolicyFactory.java
new file mode 100644
index 00000000000..0fc750d1f71
--- /dev/null
+++ b/solr/test-framework/src/java/org/apache/solr/util/RandomNoReverseMergePolicyFactory.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util;
+
+import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
+import org.apache.lucene.index.MergePolicy;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.index.MergePolicyFactory;
+import org.apache.solr.index.MergePolicyFactoryArgs;
+import org.junit.rules.TestRule;
+
+/**
+ * A {@link MergePolicyFactory} for {@link RandomMergePolicy} preventing random segment reversing.
+ * It's absolutely necessary for all block join dependent tests. Without it, they may unexpectedly
+ * fail from time to time.
+ */
+public final class RandomNoReverseMergePolicyFactory extends MergePolicyFactory {
+
+  /**
+   * This rule works because all solrconfig*.xml files include
+   * solrconfig.snippet.randomindexconfig.xml where this property is used. If one refuse to include
+   * it, test may unexpectedly fail from time to time.
+   */
+  public static TestRule createRule() {
+    return new SystemPropertiesRestoreRule(
+        SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_MERGEPOLICYFACTORY,
+        RandomNoReverseMergePolicyFactory.class.getName());
+  }
+
+  public RandomNoReverseMergePolicyFactory() {
+    super(null, new MergePolicyFactoryArgs(), null);
+  }
+
+  @Override
+  public MergePolicy getMergePolicy() {
+    final boolean allowReverse = false;
+    return new RandomMergePolicy(allowReverse);
+  }
+}