You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by gu...@apache.org on 2020/02/28 02:40:46 UTC
[lucene-solr] branch branch_8x updated: SOLR-14283 - fix NPE in
SolrTestCaseJ4
This is an automated email from the ASF dual-hosted git repository.
gus pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8x by this push:
new 9c9a69c SOLR-14283 - fix NPE in SolrTestCaseJ4
9c9a69c is described below
commit 9c9a69c643243caee119666c50434b1cf485d0ca
Author: Gus Heck <gu...@apache.org>
AuthorDate: Wed Feb 26 09:15:35 2020 -0500
SOLR-14283 - fix NPE in SolrTestCaseJ4
---
.../test/org/apache/solr/SolrTestCaseJ4Test.java | 9 +
.../test/org/apache/solr/SourceHomeNullifier.java | 75 +++++
.../src/java/org/apache/solr/SolrTestCaseJ4.java | 318 +++++++++++----------
3 files changed, 244 insertions(+), 158 deletions(-)
diff --git a/solr/core/src/test/org/apache/solr/SolrTestCaseJ4Test.java b/solr/core/src/test/org/apache/solr/SolrTestCaseJ4Test.java
index fc995e3..1799699 100644
--- a/solr/core/src/test/org/apache/solr/SolrTestCaseJ4Test.java
+++ b/solr/core/src/test/org/apache/solr/SolrTestCaseJ4Test.java
@@ -22,11 +22,20 @@ import org.apache.commons.io.FileUtils;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.junit.AfterClass;
import org.junit.BeforeClass;
+import org.junit.ClassRule;
import org.junit.Test;
public class SolrTestCaseJ4Test extends SolrTestCaseJ4 {
+ /**
+ * Randomly test that it is possible to use SolrTestCaseJ4 even if
+ * {@link org.apache.solr.util.ExternalPaths#SOURCE_HOME} is null. This
+ * will be common for usages of Solr Test Framework outside of solr.
+ */
+ @ClassRule
+ public static final SourceHomeNullifier shn = new SourceHomeNullifier();
+
private static String tmpSolrHome;
@BeforeClass
diff --git a/solr/core/src/test/org/apache/solr/SourceHomeNullifier.java b/solr/core/src/test/org/apache/solr/SourceHomeNullifier.java
new file mode 100644
index 0000000..e3dff56
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/SourceHomeNullifier.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import com.carrotsearch.randomizedtesting.RandomizedContext;
+import org.apache.solr.common.util.SuppressForbidden;
+import org.apache.solr.util.ExternalPaths;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import static org.junit.Assert.fail;
+
+public class SourceHomeNullifier extends TestWatcher {
+
+ private String oldSourceHome;
+ private Field sourceHomeField;
+
+ @Override
+ protected void starting(Description description) {
+ boolean nullify = RandomizedContext.current().getRandom().nextBoolean();
+ if (nullify) {
+ oldSourceHome = ExternalPaths.SOURCE_HOME;
+ try {
+ sourceHomeField = ExternalPaths.class.getDeclaredField("SOURCE_HOME");
+ setFinalStatic(sourceHomeField, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ super.starting(description);
+ }
+
+ @SuppressForbidden(reason = "Need to tweak the value of a static final field on a per test basis")
+ static void setFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+
+ field.set(null, newValue);
+ }
+
+ @Override
+ protected void finished(Description description) {
+ if (sourceHomeField != null) {
+ try {
+ sourceHomeField.set(null, oldSourceHome);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ super.finished(description);
+ }
+}
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index ad07cb7..19c3b68 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -191,7 +191,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
"java.lang.reflect.",
"com.carrotsearch.randomizedtesting.",
});
-
+
public static final String DEFAULT_TEST_COLLECTION_NAME = "collection1";
public static final String DEFAULT_TEST_CORENAME = DEFAULT_TEST_COLLECTION_NAME;
protected static final String CORE_PROPERTIES_FILENAME = "core.properties";
@@ -204,9 +204,9 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
protected static String coreName = DEFAULT_TEST_CORENAME;
public static int DEFAULT_CONNECTION_TIMEOUT = 60000; // default socket connection timeout in ms
-
+
private static String initialRootLogLevel;
-
+
protected volatile static ExecutorService testExecutor;
protected void writeCoreProperties(Path coreDirectory, String corename) throws IOException {
@@ -239,7 +239,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/** Point to JIRA entry. */
public String bugUrl() default "None";
}
-
+
/**
* Annotation for test classes that want to disable PointFields.
* PointFields will otherwise randomly used by some schemas.
@@ -252,13 +252,13 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/** Point to JIRA entry. */
public String bugUrl();
}
-
+
// these are meant to be accessed sequentially, but are volatile just to ensure any test
// thread will read the latest value
protected static volatile SSLTestConfig sslConfig;
@Rule
- public TestRule solrTestRules =
+ public TestRule solrTestRules =
RuleChain.outerRule(new SystemPropertiesRestoreRule());
@BeforeClass
@@ -266,7 +266,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
initialRootLogLevel = StartupLoggingUtils.getLogLevelString();
initClassLogLevels();
resetExceptionIgnores();
-
+
testExecutor = new ExecutorUtil.MDCAwareThreadPoolExecutor(0, Integer.MAX_VALUE,
15L, TimeUnit.SECONDS,
new SynchronousQueue<>(),
@@ -274,14 +274,16 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
true);
// set solr.install.dir needed by some test configs outside of the test sandbox (!)
- System.setProperty("solr.install.dir", ExternalPaths.SOURCE_HOME);
+ if (ExternalPaths.SOURCE_HOME != null) {
+ System.setProperty("solr.install.dir", ExternalPaths.SOURCE_HOME);
+ }
// not strictly needed by this class at this point in the control lifecycle, but for
// backcompat create it now in case any third party tests expect initCoreDataDir to be
// non-null after calling setupTestCases()
initAndGetDataDir();
- System.setProperty("solr.zkclienttimeout", "90000");
-
+ System.setProperty("solr.zkclienttimeout", "90000");
+
System.setProperty("solr.httpclient.retries", "1");
System.setProperty("solr.retries.on.forward", "1");
System.setProperty("solr.retries.to.followers", "1");
@@ -318,7 +320,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
} catch (Exception e) {
log.error("Error deleting SolrCore.");
}
-
+
if (null != testExecutor) {
ExecutorUtil.shutdownAndAwaitTermination(testExecutor);
testExecutor = null;
@@ -366,7 +368,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
StartupLoggingUtils.changeLogLevel(initialRootLogLevel);
}
}
-
+
/**
* a "dead" host, if you try to connect to it, it will likely fail fast
* please consider using mocks and not real networking to simulate failure
@@ -395,14 +397,14 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
fail("ByteBuddy and Mockito are not available on classpath: " + e.toString());
}
}
-
+
/**
* @return null if ok else error message
*/
public static String clearObjectTrackerAndCheckEmpty(int waitSeconds) {
return clearObjectTrackerAndCheckEmpty(waitSeconds, false);
}
-
+
/**
* @return null if ok else error message
*/
@@ -430,12 +432,12 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
} catch (InterruptedException e) { break; }
}
while (retries++ < waitSeconds);
-
-
+
+
log.info("------------------------------------------------------- Done waiting for tracked resources to be released");
-
+
ObjectReleaseTracker.clear();
-
+
return result;
}
@@ -470,7 +472,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
LogLevel.Configurer.restoreLogLevels(savedMethodLogLevels);
savedMethodLogLevels.clear();
}
-
+
protected static boolean isSSLMode() {
return sslConfig != null && sslConfig.isSSLMode();
}
@@ -506,7 +508,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
SSLRandomizer sslRandomizer =
SSLRandomizer.getSSLRandomizerForClass(RandomizedContext.current().getTargetClass());
-
+
if (Constants.MAC_OS_X) {
// see SOLR-9039
// If a solution is found to remove this, please make sure to also update
@@ -523,7 +525,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
protected static JettyConfig buildJettyConfig(String context) {
return JettyConfig.builder().setContext(context).withSSLConfig(sslConfig.buildServerSSLConfig()).build();
}
-
+
protected static String buildUrl(final int port, final String context) {
return (isSSLMode() ? "https" : "http") + "://127.0.0.1:" + port + context;
}
@@ -555,11 +557,11 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
h = new TestHarness(SolrXmlConfig.fromSolrHome(solrHome));
lrf = h.getRequestFactory("/select", 0, 20, CommonParams.VERSION, "2.2");
}
-
- /**
+
+ /**
* Sets system properties to allow generation of random configurations of
- * solrconfig.xml and schema.xml.
- * Sets properties used on
+ * solrconfig.xml and schema.xml.
+ * Sets properties used on
* {@link #newIndexWriterConfig(org.apache.lucene.analysis.Analyzer)}
* and base schema.xml (Point Fields)
*/
@@ -596,17 +598,17 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
@Override
public void tearDown() throws Exception {
- log.info("###Ending " + getTestName());
+ log.info("###Ending " + getTestName());
super.tearDown();
}
/**
- * Subclasses may call this method to access the "dataDir" that will be used by
+ * Subclasses may call this method to access the "dataDir" that will be used by
* {@link #initCore} (either prior to or after the core is created).
* <p>
* If the dataDir has not yet been initialized when this method is called, this method will do so.
- * Calling {@link #deleteCore} will "reset" the value, such that subsequent calls will
- * re-initialize a new value. All directories returned by any calls to this method will
+ * Calling {@link #deleteCore} will "reset" the value, such that subsequent calls will
+ * re-initialize a new value. All directories returned by any calls to this method will
* automatically be cleaned up per {@link #createTempDir}
* </p>
* <p>
@@ -627,17 +629,17 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
return dataDir;
}
- /**
- * Counter for ensuring we don't ask {@link #createTempDir} to try and
+ /**
+ * Counter for ensuring we don't ask {@link #createTempDir} to try and
* re-create the same dir prefix over and over.
* <p>
- * (createTempDir has it's own counter for uniqueness, but it tries all numbers in a loop
- * until it finds one available. No reason to force that O(N^2) behavior when we know we've
+ * (createTempDir has it's own counter for uniqueness, but it tries all numbers in a loop
+ * until it finds one available. No reason to force that O(N^2) behavior when we know we've
* already created N previous directories with the same prefix.)
* </p>
*/
private static final AtomicInteger dataDirCount = new AtomicInteger(0);
-
+
/** Call initCore in @BeforeClass to instantiate a solr core in your test class.
* deleteCore will be called for you via SolrTestCaseJ4 @AfterClass */
public static void initCore(String config, String schema) throws Exception {
@@ -661,7 +663,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
coreName=pCoreName;
initCore(config,schema,solrHome);
}
-
+
static long numOpens;
static long numCloses;
public static void startTrackingSearchers() {
@@ -673,7 +675,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
numOpens = numCloses = 0;
}
}
-
+
/** Causes an exception matching the regex pattern to not be logged. */
public static void ignoreException(String pattern) {
if (SolrException.ignorePatterns == null) // usually initialized already but in case not...
@@ -746,10 +748,10 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
/**
- * The directory used as the <code>dataDir</code> for the TestHarness unless
- * {@link #hdfsDataDir} is non null.
+ * The directory used as the <code>dataDir</code> for the TestHarness unless
+ * {@link #hdfsDataDir} is non null.
* <p>
- * Will be set to null by {@link #deleteCore} and re-initialized as needed by {@link #createCore}.
+ * Will be set to null by {@link #deleteCore} and re-initialized as needed by {@link #createCore}.
* In the event of a test failure, the contents will be left on disk.
* </p>
* @see #createTempDir(String)
@@ -758,7 +760,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
*/
@Deprecated
protected static volatile File initCoreDataDir;
-
+
// hack due to File dataDir
protected static String hdfsDataDir;
@@ -897,7 +899,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
// clears the updatelog sysprop at the end of the test run
System.clearProperty(UPDATELOG_SYSPROP);
}
-
+
solrConfig = null;
h = null;
lrf = null;
@@ -1098,7 +1100,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
} finally {
if (failed) {
- log.error("JSON query validation threw an exception." +
+ log.error("JSON query validation threw an exception." +
"\n expected =" + testJSON +
"\n response = " + response +
"\n request = " + req.getParamString()
@@ -1111,7 +1113,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
// restore the params
if (params != null && params != req.getParams()) req.setParams(params);
}
- }
+ }
/** Makes sure a query throws a SolrException with the listed response code */
@@ -1156,7 +1158,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
fail( failMessage );
} catch (SolrException e) {
assertEquals( code.code, e.code() );
- assertTrue("Unexpected error message. Expecting \"" + exceptionMessage +
+ assertTrue("Unexpected error message. Expecting \"" + exceptionMessage +
"\" but got \"" + e.getMessage() + "\"", e.getMessage()!= null && e.getMessage().contains(exceptionMessage));
} catch (Exception e2) {
throw new RuntimeException("Exception during query", e2);
@@ -1350,11 +1352,11 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
/**
- * Does a low level delete of all docs in the index.
+ * Does a low level delete of all docs in the index.
*
* The behavior of this method is slightly different then doing a normal <code>*:*</code> DBQ because it
- * takes advantage of internal methods to ensure all index data is wiped, regardless of optimistic
- * concurrency version constraints -- making it suitable for tests that create synthetic versions,
+ * takes advantage of internal methods to ensure all index data is wiped, regardless of optimistic
+ * concurrency version constraints -- making it suitable for tests that create synthetic versions,
* and/or require a completely pristine index w/o any field metdata.
*
* @see #deleteByQueryAndGetVersion
@@ -1617,7 +1619,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// random document / index creation ///////////////////////
/////////////////////////////////////////////////////////////////////////////////////
-
+
public abstract static class Vals {
public abstract Comparable get();
public String toJSON(Comparable val) {
@@ -1814,7 +1816,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
public FldType(String fname, IVals numValues, Vals vals) {
this.fname = fname;
this.numValues = numValues;
- this.vals = vals;
+ this.vals = vals;
}
public Comparable createValue() {
@@ -1837,7 +1839,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
Fld fld = new Fld();
fld.ftype = this;
fld.vals = vals;
- return fld;
+ return fld;
}
}
@@ -1874,7 +1876,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
// duplicate 10% of the docs
if (random().nextInt(10)==0) {
updateJ(toJSON(doc), null);
- model.put(doc.id, doc);
+ model.put(doc.id, doc);
}
}
@@ -1954,7 +1956,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
if (comparators.size() == 0) {
// default sort is by score desc
- comparators.add(createComparator("score", false, false, false, false));
+ comparators.add(createComparator("score", false, false, false, false));
}
return createComparator(comparators);
@@ -2090,7 +2092,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
try {
return new File(url.toURI());
} catch (Exception e) {
- throw new RuntimeException("Resource was found on classpath, but cannot be resolved to a " +
+ throw new RuntimeException("Resource was found on classpath, but cannot be resolved to a " +
"normal file (maybe it is part of a JAR file): " + name);
}
}
@@ -2100,7 +2102,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
throw new RuntimeException("Cannot find resource in classpath or in file-system (relative to CWD): " + name);
}
-
+
public static String TEST_HOME() {
return getFile("solr/collection1").getParent();
}
@@ -2134,7 +2136,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
throw new RuntimeException("XPath is invalid", e2);
}
}
-
+
/**
* Fails if the number of documents in the given SolrDocumentList differs
* from the given number of expected values, or if any of the values in the
@@ -2202,7 +2204,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
File xmlF = new File(SolrTestCaseJ4.TEST_HOME(), fromFile);
FileUtils.copyFile(xmlF, new File(dstRoot, "solr.xml"));
-
+
}
// Creates a consistent configuration, _including_ solr.xml at dstRoot. Creates collection1/conf and copies
// the stock files in there.
@@ -2294,7 +2296,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
if (list1.getMaxScore() == null) {
if (list2.getMaxScore() != null) {
return false;
- }
+ }
} else if (list2.getMaxScore() == null) {
return false;
} else {
@@ -2406,7 +2408,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
return true;
}
- /**
+ /**
* Returns <code>likely</code> most (1/10) of the time, otherwise <code>unlikely</code>
*/
public static Object skewed(Object likely, Object unlikely) {
@@ -2473,27 +2475,27 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
* some internal settings.
*/
public static class CloudSolrClientBuilder extends CloudSolrClient.Builder {
-
+
public CloudSolrClientBuilder(List<String> zkHosts, Optional<String> zkChroot) {
super(zkHosts, zkChroot);
randomizeCloudSolrClient();
}
-
+
public CloudSolrClientBuilder(ClusterStateProvider stateProvider) {
this.stateProvider = stateProvider;
randomizeCloudSolrClient();
}
-
+
public CloudSolrClientBuilder(MiniSolrCloudCluster cluster) {
if (random().nextBoolean()) {
this.zkHosts.add(cluster.getZkServer().getZkAddress());
} else {
populateSolrUrls(cluster);
}
-
+
randomizeCloudSolrClient();
}
-
+
private void populateSolrUrls(MiniSolrCloudCluster cluster) {
if (random().nextBoolean()) {
final List<JettySolrRunner> solrNodes = cluster.getJettySolrRunners();
@@ -2504,7 +2506,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
this.solrUrls.add(cluster.getRandomJetty(random()).getBaseUrl().toString());
}
}
-
+
private void randomizeCloudSolrClient() {
this.directUpdatesToLeadersOnly = random().nextBoolean();
this.shardLeadersOnly = random().nextBoolean();
@@ -2516,7 +2518,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
* Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty()).build();
}
@@ -2532,20 +2534,20 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, HttpClient httpClient) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
.withHttpClient(httpClient)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly) {
if (shardLeadersOnly) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
@@ -2563,9 +2565,9 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, int socketTimeoutMillis) {
if (shardLeadersOnly) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
@@ -2578,12 +2580,12 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withSocketTimeout(socketTimeoutMillis)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, int connectionTimeoutMillis, int socketTimeoutMillis) {
if (shardLeadersOnly) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
@@ -2598,14 +2600,14 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withSocketTimeout(socketTimeoutMillis)
.build();
}
-
-
-
+
+
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, HttpClient httpClient) {
if (shardLeadersOnly) {
return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
@@ -2618,12 +2620,12 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.sendUpdatesToAllReplicasInShard()
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
- */
+ */
public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, HttpClient httpClient,
int connectionTimeoutMillis, int socketTimeoutMillis) {
if (shardLeadersOnly) {
@@ -2641,24 +2643,24 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withSocketTimeout(socketTimeoutMillis)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
- */
+ */
public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(String baseSolrUrl, int queueSize, int threadCount) {
return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
.withQueueSize(queueSize)
.withThreadCount(threadCount)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
- */
+ */
public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(String baseSolrUrl, int queueSize, int threadCount, int connectionTimeoutMillis) {
return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
.withQueueSize(queueSize)
@@ -2666,12 +2668,12 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withConnectionTimeout(connectionTimeoutMillis)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder} class directly
- */
+ */
public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(String baseSolrUrl, HttpClient httpClient, int queueSize, int threadCount) {
return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
.withHttpClient(httpClient)
@@ -2679,24 +2681,24 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withThreadCount(threadCount)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
- */
+ */
public static LBHttpSolrClient getLBHttpSolrClient(HttpClient client, String... solrUrls) {
return new LBHttpSolrClient.Builder()
.withHttpClient(client)
.withBaseSolrUrls(solrUrls)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
- */
+ */
public static LBHttpSolrClient getLBHttpSolrClient(HttpClient client, int connectionTimeoutMillis,
int socketTimeoutMillis, String... solrUrls) {
return new LBHttpSolrClient.Builder()
@@ -2706,23 +2708,23 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.withSocketTimeout(socketTimeoutMillis)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder} class directly
- */
+ */
public static LBHttpSolrClient getLBHttpSolrClient(String... solrUrls) throws MalformedURLException {
return new LBHttpSolrClient.Builder()
.withBaseSolrUrls(solrUrls)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient, ResponseParser responseParser, boolean compression) {
return new Builder(url)
.withHttpClient(httpClient)
@@ -2730,35 +2732,35 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.allowCompression(compression)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient, ResponseParser responseParser) {
return new Builder(url)
.withHttpClient(httpClient)
.withResponseParser(responseParser)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient) {
return new Builder(url)
.withHttpClient(httpClient)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient, int connectionTimeoutMillis) {
return new Builder(url)
.withHttpClient(httpClient)
@@ -2768,30 +2770,30 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url) {
return new Builder(url)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, int connectionTimeoutMillis) {
return new Builder(url)
.withConnectionTimeout(connectionTimeoutMillis)
.build();
}
-
+
/**
* This method <i>may</i> randomize unspecified aspects of the resulting SolrClient.
- * Tests that do not wish to have any randomized behavior should use the
+ * Tests that do not wish to have any randomized behavior should use the
* {@link org.apache.solr.client.solrj.impl.HttpSolrClient.Builder} class directly
- */
+ */
public static HttpSolrClient getHttpSolrClient(String url, int connectionTimeoutMillis, int socketTimeoutMillis) {
return new Builder(url)
.withConnectionTimeout(connectionTimeoutMillis)
@@ -2799,18 +2801,18 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
.build();
}
- /**
- * Returns a randomly generated Date in the appropriate Solr external (input) format
+ /**
+ * Returns a randomly generated Date in the appropriate Solr external (input) format
* @see #randomSkewedDate
*/
public static String randomDate() {
return Instant.ofEpochMilli(random().nextLong()).toString();
}
- /**
- * Returns a Date such that all results from this method always have the same values for
- * year+month+day+hour+minute but the seconds are randomized. This can be helpful for
- * indexing documents with random date values that are biased for a narrow window
+ /**
+ * Returns a Date such that all results from this method always have the same values for
+ * year+month+day+hour+minute but the seconds are randomized. This can be helpful for
+ * indexing documents with random date values that are biased for a narrow window
* (one day) to test collisions/overlaps
*
* @see #randomDate
@@ -2831,7 +2833,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
return result;
}
-
+
protected static void waitForWarming(SolrCore core) throws InterruptedException {
RefCounted<SolrIndexSearcher> registeredSearcher = core.getRegisteredSearcher();
RefCounted<SolrIndexSearcher> newestSearcher = core.getNewestSearcher(false);
@@ -2862,7 +2864,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
return testName;
}
-
+
@BeforeClass
public static void assertNonBlockingRandomGeneratorAvailable() throws InterruptedException {
final String EGD = "java.security.egd";
@@ -2870,36 +2872,36 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
final String ALLOWED = "test.solr.allowed.securerandom";
final String allowedAlg = System.getProperty(ALLOWED);
final String actualEGD = System.getProperty(EGD);
-
+
log.info("SecureRandom sanity checks: {}={} & {}={}", ALLOWED, allowedAlg, EGD, actualEGD);
if (null != allowedAlg) {
// the user has explicitly requested to bypass our assertions and allow a particular alg
// the only thing we should do is assert that the algorithm they have whitelisted is actaully used
-
-
+
+
final String actualAlg = (new SecureRandom()).getAlgorithm();
assertEquals("Algorithm specified using "+ALLOWED+" system property " +
"does not match actual algorithm", allowedAlg, actualAlg);
return;
}
- // else: no user override, do the checks we want including
-
+ // else: no user override, do the checks we want including
+
if (null == actualEGD) {
System.setProperty(EGD, URANDOM);
log.warn("System property {} was not set by test runner, forcibly set to expected: {}", EGD, URANDOM);
} else if (! URANDOM.equals(actualEGD) ) {
log.warn("System property {}={} .. test runner should use expected: {}", EGD, actualEGD, URANDOM);
}
-
+
final String algorithm = (new SecureRandom()).getAlgorithm();
-
+
assertFalse("SecureRandom algorithm '" + algorithm + "' is in use by your JVM, " +
"which is a potentially blocking algorithm on some environments. " +
"Please report the details of this failure (and your JVM vendor/version) to solr-user@lucene.apache.org. " +
"You can try to run your tests with -D"+EGD+"="+URANDOM+" or bypass this check using " +
"-Dtest.solr.allowed.securerandom="+ algorithm +" as a JVM option when running tests.",
- // be permissive in our checks and blacklist only algorithms
+ // be permissive in our checks and blacklist only algorithms
// that are known to be blocking under some circumstances
algorithm.equals("NativePRNG") || algorithm.equals("NativePRNGBlocking"));
}
@@ -2911,7 +2913,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
protected static void systemClearPropertySolrTestsMergePolicyFactory() {
System.clearProperty(SYSTEM_PROPERTY_SOLR_TESTS_MERGEPOLICYFACTORY);
}
-
+
@Deprecated // For backwards compatibility only. Please do not use in new tests.
protected static void systemSetPropertySolrDisableShardsWhitelist(String value) {
System.setProperty(SYSTEM_PROPERTY_SOLR_DISABLE_SHARDS_WHITELIST, value);
@@ -2925,9 +2927,9 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
protected <T> T pickRandom(T... options) {
return options[random().nextInt(options.length)];
}
-
+
/**
- * The name of a sysprop that can be set by users when running tests to force the types of numerics
+ * The name of a sysprop that can be set by users when running tests to force the types of numerics
* used for test classes that do not have the {@link SuppressPointFields} annotation:
* <ul>
* <li>If unset, then a random variable will be used to decide the type of numerics.</li>
@@ -2937,23 +2939,23 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
* @see #NUMERIC_POINTS_SYSPROP
*/
public static final String USE_NUMERIC_POINTS_SYSPROP = "solr.tests.use.numeric.points";
-
+
/**
- * The name of a sysprop that will either <code>true</code> or <code>false</code> indicating if
- * numeric points fields are currently in use, depending on the user specified value of
- * {@link #USE_NUMERIC_POINTS_SYSPROP} and/or the {@link SuppressPointFields} annotation and/or
+ * The name of a sysprop that will either <code>true</code> or <code>false</code> indicating if
+ * numeric points fields are currently in use, depending on the user specified value of
+ * {@link #USE_NUMERIC_POINTS_SYSPROP} and/or the {@link SuppressPointFields} annotation and/or
* randomization. Tests can use <code>Boolean.getBoolean(NUMERIC_POINTS_SYSPROP)</code>.
*
* @see #randomizeNumericTypesProperties
*/
public static final String NUMERIC_POINTS_SYSPROP = "solr.tests.numeric.points";
-
+
/**
- * The name of a sysprop that will be either <code>true</code> or <code>false</code> indicating if
- * docValues should be used on a numeric field. This property string should be used in the
- * <code>docValues</code> attribute of (most) numeric fieldTypes in schemas, and by default will be
- * randomized by this class in a <code>@BeforeClass</code>. Subclasses that need to force specific
- * behavior can use <code>System.setProperty(NUMERIC_DOCVALUES_SYSPROP,"true")</code>
+ * The name of a sysprop that will be either <code>true</code> or <code>false</code> indicating if
+ * docValues should be used on a numeric field. This property string should be used in the
+ * <code>docValues</code> attribute of (most) numeric fieldTypes in schemas, and by default will be
+ * randomized by this class in a <code>@BeforeClass</code>. Subclasses that need to force specific
+ * behavior can use <code>System.setProperty(NUMERIC_DOCVALUES_SYSPROP,"true")</code>
* to override the default randomization.
*
* @see #randomizeNumericTypesProperties
@@ -2975,7 +2977,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
/**
- * Sets various sys props related to user specified or randomized choices regarding the types
+ * Sets various sys props related to user specified or randomized choices regarding the types
* of numerics that should be used in tests.
*
* @see #NUMERIC_DOCVALUES_SYSPROP
@@ -2988,17 +2990,17 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
final boolean useDV = random().nextBoolean();
System.setProperty(NUMERIC_DOCVALUES_SYSPROP, ""+useDV);
-
+
// consume a consistent amount of random data even if sysprop/annotation is set
final boolean randUsePoints = 0 != random().nextInt(5); // 80% likelihood
final String usePointsStr = System.getProperty(USE_NUMERIC_POINTS_SYSPROP);
final boolean usePoints = (null == usePointsStr) ? randUsePoints : Boolean.parseBoolean(usePointsStr);
-
+
if (RandomizedContext.current().getTargetClass().isAnnotationPresent(SolrTestCaseJ4.SuppressPointFields.class)
|| (! usePoints)) {
log.info("Using TrieFields (NUMERIC_POINTS_SYSPROP=false) w/NUMERIC_DOCVALUES_SYSPROP="+useDV);
-
+
org.apache.solr.schema.PointField.TEST_HACK_IGNORE_USELESS_TRIEFIELD_ARGS = false;
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Integer.class, "solr.TrieIntField");
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Float.class, "solr.TrieFloatField");
@@ -3006,7 +3008,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Double.class, "solr.TrieDoubleField");
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Date.class, "solr.TrieDateField");
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Enum.class, "solr.EnumField");
-
+
System.setProperty(NUMERIC_POINTS_SYSPROP, "false");
} else {
log.info("Using PointFields (NUMERIC_POINTS_SYSPROP=true) w/NUMERIC_DOCVALUES_SYSPROP="+useDV);
@@ -3018,7 +3020,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Double.class, "solr.DoublePointField");
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Date.class, "solr.DatePointField");
private_RANDOMIZED_NUMERIC_FIELDTYPES.put(Enum.class, "solr.EnumFieldType");
-
+
System.setProperty(NUMERIC_POINTS_SYSPROP, "true");
}
for (Map.Entry<Class,String> entry : RANDOMIZED_NUMERIC_FIELDTYPES.entrySet()) {
@@ -3035,7 +3037,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
return new DistributedUpdateProcessor(req, rsp, next);
}
-
+
/**
* Cleans up the randomized sysproperties and variables set by {@link #randomizeNumericTypesProperties}
*
@@ -3073,7 +3075,7 @@ public abstract class SolrTestCaseJ4 extends SolrTestCase {
}
private static final Map<Class,String> private_RANDOMIZED_NUMERIC_FIELDTYPES = new HashMap<>();
-
+
/**
* A Map of "primitive" java "numeric" types and the string name of the <code>class</code> used in the
* corresponding schema fieldType declaration.