diff --git a/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java b/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java index e8a11f181a7..df4ab85494b 100644 --- a/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java +++ b/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java @@ -20,8 +20,10 @@ import java.util.Set; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.search.CallerSpecificQueryLimit; +import org.apache.solr.util.QueryLimitsTestInjectionRule; import org.apache.solr.util.TestInjection; import org.junit.After; +import org.junit.BeforeClass; import org.junit.Test; public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 { @@ -44,6 +46,11 @@ public static void createIndex() { assertU(commit()); } + @BeforeClass + public static void beforeClass() throws Exception { + QueryLimitsTestInjectionRule.disable(); + } + @After public void tearDownCore() { deleteCore(); diff --git a/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java b/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java index 47da28286ad..b71d1ed932f 100644 --- a/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java +++ b/solr/core/src/test/org/apache/solr/search/TestRangeQuery.java @@ -463,8 +463,14 @@ public void testRangeQueryWithFilterCache() throws Exception { queryService.awaitTermination( 1, TimeUnit.SECONDS)); // All queries after should be very fast - assertEquals( - "Create only one DocSet outside of cache", 1, TestInjection.countDocSetDelays.get()); + if (TestInjection.queryTimeout != null) { + assertTrue( + "Create multiple DocSet-s outside of cache because of possible query timeouts", + TestInjection.countDocSetDelays.get() > 0); + } else { + assertEquals( + "Create only one DocSet outside of cache", 1, TestInjection.countDocSetDelays.get()); + } } TestInjection.countDocSetDelays.set(0); } diff --git a/solr/modules/ltr/src/test/org/apache/solr/ltr/TestLTRQParserPlugin.java b/solr/modules/ltr/src/test/org/apache/solr/ltr/TestLTRQParserPlugin.java index 8f5f140f4fd..a835918ea1a 100644 --- a/solr/modules/ltr/src/test/org/apache/solr/ltr/TestLTRQParserPlugin.java +++ b/solr/modules/ltr/src/test/org/apache/solr/ltr/TestLTRQParserPlugin.java @@ -196,10 +196,7 @@ public void ltr_expensiveFeatureRescoringAndPartialResultsNotTolerated_shouldRai assertJQ( "/query" + query.toQueryString(), - "/error/msg=='org.apache.solr.search.QueryLimitsExceededException: Limits exceeded! (Learning To Rank rescoring - " - + "The full reranking didn\\'t complete. " - + "If partial results are tolerated the reranking got reverted and all documents preserved their original score and ranking.)" - + ": Query limits: [TimeAllowedLimit:LIMIT EXCEEDED]'"); + "/error/msg=='///regex:.*Limits exceeded\\!.*Learning To Rank rescoring.*///'"); } @Test diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java index d1c3e539bf1..ad0857dee74 100644 --- a/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java +++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java @@ -38,6 +38,7 @@ import org.apache.solr.core.ConfigSetService; import org.apache.solr.util.ExternalPaths; import org.apache.solr.util.LogLevelTestRule; +import org.apache.solr.util.QueryLimitsTestInjectionRule; import org.apache.solr.util.RevertDefaultThreadHandlerRule; import org.apache.solr.util.StartupLoggingUtils; import org.hamcrest.Matcher; @@ -91,6 +92,7 @@ public class SolrTestCase extends LuceneTestCase { "org.apache.solr.ltr", NAMING_CONVENTION_TEST_PREFIX)) .around(new RevertDefaultThreadHandlerRule()) .around(new LogLevelTestRule()) + .around(new QueryLimitsTestInjectionRule(LuceneTestCase::rarely)) .around( new TestRuleAdapter() { @Override diff --git a/solr/test-framework/src/java/org/apache/solr/util/QueryLimitsTestInjectionRule.java b/solr/test-framework/src/java/org/apache/solr/util/QueryLimitsTestInjectionRule.java new file mode 100644 index 00000000000..d755c9cd918 --- /dev/null +++ b/solr/test-framework/src/java/org/apache/solr/util/QueryLimitsTestInjectionRule.java @@ -0,0 +1,78 @@ +/* + * 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 java.lang.invoke.MethodHandles; +import java.util.function.BooleanSupplier; +import org.apache.solr.search.QueryLimit; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QueryLimitsTestInjectionRule implements TestRule { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final BooleanSupplier FALSE = () -> false; + private static BooleanSupplier enableSupplier; + + public QueryLimitsTestInjectionRule(BooleanSupplier enableSupplier) { + QueryLimitsTestInjectionRule.enableSupplier = enableSupplier; + } + + @Override + public Statement apply(final Statement base, final Description description) { + if (!enableSupplier.getAsBoolean()) { + return base; + } + return new Statement() { + @Override + public void evaluate() throws Throwable { + if (!enableSupplier.getAsBoolean()) { + base.evaluate(); + return; + } + log.info("###Test is configured to use QueryLimits"); + try { + assert TestInjection.queryTimeout == null : "Disabled too late, or was init'ed elsewhere"; + TestInjection.queryTimeout = + new QueryLimit() { + @Override + public Object currentValue() { + return "No-Op injected QueryLimit"; + } + + @Override + public boolean shouldExit() { + return false; + } + }; + + base.evaluate(); + } finally { + // always reset the queryTimeout + TestInjection.queryTimeout = null; + } + } + }; + } + + /** Disables for the whole test suite (class), not just for this individual test. */ + public static void disable() { + QueryLimitsTestInjectionRule.enableSupplier = FALSE; + } +}