You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2020/12/02 17:24:54 UTC

[lucene-solr] branch master updated: SOLR-14934: Refactored duplicate "Solr Home" logic into a single place to eliminate risk of tests using divergent values for a single solr node.

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

hossman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e6a023  SOLR-14934: Refactored duplicate "Solr Home" logic into a single place to eliminate risk of tests using divergent values for a single solr node.
2e6a023 is described below

commit 2e6a02394ec4eea6ba72d5bc2bf02c0139a54f39
Author: Chris Hostetter <ho...@apache.org>
AuthorDate: Wed Dec 2 10:24:36 2020 -0700

    SOLR-14934: Refactored duplicate "Solr Home" logic into a single place to eliminate risk of tests using divergent values for a single solr node.
---
 solr/CHANGES.txt                                   | 11 +++
 .../apache/solr/ltr/TestLTRReRankingPipeline.java  |  3 +-
 .../org/apache/solr/ltr/TestLTRScoringQuery.java   |  3 +-
 .../test/org/apache/solr/ltr/TestRerankBase.java   |  3 +-
 .../apache/solr/ltr/norm/TestMinMaxNormalizer.java |  5 +-
 .../solr/ltr/norm/TestStandardNormalizer.java      |  5 +-
 .../src/java/org/apache/solr/core/NodeConfig.java  |  2 +
 .../src/java/org/apache/solr/core/SolrPaths.java   |  5 +-
 .../org/apache/solr/core/SolrResourceLoader.java   | 14 +++-
 .../java/org/apache/solr/core/XmlConfigFile.java   |  5 +-
 .../org/apache/solr/search/SolrCoreParser.java     | 13 ++-
 .../apache/solr/servlet/SolrDispatchFilter.java    | 14 +++-
 .../test/org/apache/solr/cloud/OverseerTest.java   |  2 +-
 .../org/apache/solr/core/ResourceLoaderTest.java   |  7 +-
 .../org/apache/solr/core/TestCoreContainer.java    | 22 +++++
 .../org/apache/solr/core/TestCoreDiscovery.java    |  3 +-
 .../solr/index/WrapperMergePolicyFactoryTest.java  |  2 +-
 .../apache/solr/metrics/SolrMetricManagerTest.java | 94 +++++++++++-----------
 .../org/apache/solr/search/TestSolrCoreParser.java | 14 ++--
 .../org/apache/solr/search/TestXmlQParser.java     | 18 ++++-
 .../security/MultiDestinationAuditLoggerTest.java  |  5 +-
 .../client/solrj/response/QueryResponseTest.java   | 11 +--
 .../solrj/response/TestClusteringResponse.java     |  3 +-
 .../apache/solr/common/util/ContentStreamTest.java | 19 +++--
 .../src/java/org/apache/solr/util/TestHarness.java | 17 +++-
 .../solr/cloud/MiniSolrCloudClusterTest.java       | 36 +++++++++
 26 files changed, 236 insertions(+), 100 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index d2e095f..84c6cdc 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -163,6 +163,13 @@ Bug Fixes
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
 
+Upgrade Notes
+---------------------
+
+* Internal logic for identifying 'Solr Home' has been refactored to make testing less error prone.  Plugin
+  developers using SolrPaths.locateSolrHome() or 'new SolrResourceLoader' should check deprecation warnings as existing
+  some existing functionality will be removed in 9.0.  See SOLR-14934 for more details.
+
 New Features
 ---------------------
 
@@ -213,6 +220,10 @@ Bug Fixes
 * SOLR-15017: Core lib directories were not being recognized unless the solrconfig included a <lib> directive.
   (Thomas Mortagne)
 
+* SOLR-14934: Refactored duplicate "Solr Home" logic into a single place to eliminate risk of tests using divergent values
+  for a single solr node.  (hossman)
+
+
 Other Changes
 ---------------------
 
diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRReRankingPipeline.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRReRankingPipeline.java
index e921bcb..8501944 100644
--- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRReRankingPipeline.java
+++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRReRankingPipeline.java
@@ -17,6 +17,7 @@
 package org.apache.solr.ltr;
 
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -57,7 +58,7 @@ public class TestLTRReRankingPipeline extends SolrTestCase {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  private static final SolrResourceLoader solrResourceLoader = new SolrResourceLoader();
+  private static final SolrResourceLoader solrResourceLoader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
 
   private IndexSearcher getSearcher(IndexReader r) {
     // 'yes' to maybe wrapping in general
diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRScoringQuery.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRScoringQuery.java
index 973436f..71df1ed 100644
--- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRScoringQuery.java
+++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestLTRScoringQuery.java
@@ -17,6 +17,7 @@
 package org.apache.solr.ltr;
 
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -55,7 +56,7 @@ import org.junit.Test;
 
 public class TestLTRScoringQuery extends SolrTestCase {
 
-  public final static SolrResourceLoader solrResourceLoader = new SolrResourceLoader();
+  public final static SolrResourceLoader solrResourceLoader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
 
   private IndexSearcher getSearcher(IndexReader r) {
     final IndexSearcher searcher = newSearcher(r, false, false);
diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestRerankBase.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestRerankBase.java
index 5dd7cf0..bf35d3d 100644
--- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestRerankBase.java
+++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/TestRerankBase.java
@@ -21,6 +21,7 @@ import java.io.FileNotFoundException;
 import java.lang.invoke.MethodHandles;
 import java.net.URL;
 import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -53,7 +54,7 @@ public class TestRerankBase extends RestTestBase {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  protected static final SolrResourceLoader solrResourceLoader = new SolrResourceLoader();
+  protected static final SolrResourceLoader solrResourceLoader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
 
   protected static File tmpSolrHome;
   protected static File tmpConfDir;
diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestMinMaxNormalizer.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestMinMaxNormalizer.java
index 7627ae9..52e39b5 100644
--- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestMinMaxNormalizer.java
+++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestMinMaxNormalizer.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.ltr.norm;
 
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,7 +29,7 @@ import static org.junit.Assert.assertTrue;
 
 public class TestMinMaxNormalizer {
 
-  private final SolrResourceLoader solrResourceLoader = new SolrResourceLoader();
+  private final SolrResourceLoader solrResourceLoader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
 
   private Normalizer implTestMinMax(Map<String,Object> params,
       float expectedMin, float expectedMax) {
@@ -123,7 +124,7 @@ public class TestMinMaxNormalizer {
 
     final Map<String,Object> params = n1.paramsToMap();
     final MinMaxNormalizer n2 = (MinMaxNormalizer) Normalizer.getInstance(
-        new SolrResourceLoader(),
+        new SolrResourceLoader(Paths.get("").toAbsolutePath()),
         MinMaxNormalizer.class.getName(),
         params);
     assertEquals(n1.getMin(), n2.getMin(), 1e-6);
diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestStandardNormalizer.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestStandardNormalizer.java
index 62e415f..bc94337 100644
--- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestStandardNormalizer.java
+++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/norm/TestStandardNormalizer.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.ltr.norm;
 
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,7 +29,7 @@ import static org.junit.Assert.assertTrue;
 
 public class TestStandardNormalizer {
 
-  private final SolrResourceLoader solrResourceLoader = new SolrResourceLoader();
+  private final SolrResourceLoader solrResourceLoader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
 
   private Normalizer implTestStandard(Map<String,Object> params,
       float expectedAvg, float expectedStd) {
@@ -129,7 +130,7 @@ public class TestStandardNormalizer {
 
     final Map<String, Object> params = n1.paramsToMap();
     final StandardNormalizer n2 = (StandardNormalizer) Normalizer.getInstance(
-        new SolrResourceLoader(),
+        new SolrResourceLoader(Paths.get("").toAbsolutePath()),
         StandardNormalizer.class.getName(),
         params);
     assertEquals(n1.getAvg(), n2.getAvg(), 1e-6);
diff --git a/solr/core/src/java/org/apache/solr/core/NodeConfig.java b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
index 46f1807..bd2202f 100644
--- a/solr/core/src/java/org/apache/solr/core/NodeConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
@@ -136,6 +136,8 @@ public class NodeConfig {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
           "SolrCloud requires a value of at least 2 for coreLoadThreads (configured value = " + this.coreLoadThreads + ")");
     }
+    if (null == this.solrHome) throw new NullPointerException("solrHome");
+    if (null == this.loader) throw new NullPointerException("loader");
   }
 
   public String getNodeName() {
diff --git a/solr/core/src/java/org/apache/solr/core/SolrPaths.java b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
index 9819798..ad1d818 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrPaths.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrPaths.java
@@ -53,9 +53,12 @@ public final class SolrPaths {
    * <p>
    *
    * @return the Solr home, absolute and normalized.
+   * @deprecated all code should get solr home from CoreContainer
+   * @see CoreContainer#getSolrHome()
    */
+  @Deprecated
   public static Path locateSolrHome() {
-
+    
     String home = null;
     // Try JNDI
     try {
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 609da78..cae6281 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -129,6 +129,11 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
     return schemaLoader;
   }
 
+  /**
+   * @deprecated Use <code>new SolrResourceLoader(Path)</code>
+   * @see CoreContainer#getSolrHome
+   */
+  @Deprecated
   public SolrResourceLoader() {
     this(SolrPaths.locateSolrHome(), null);
   }
@@ -136,6 +141,7 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
   /**
    * Creates a loader.
    * Note: we do NOT call {@link #reloadLuceneSPI()}.
+   * (Behavior when <code>instanceDir</code> is <code>null</code> is un-specified, in future versions this will fail due to NPE)
    */
   public SolrResourceLoader(String name, List<Path> classpath, Path instanceDir, ClassLoader parent) {
     this(instanceDir, parent);
@@ -152,6 +158,10 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
   }
 
 
+  /**
+   * Creates a loader.
+   * (Behavior when <code>instanceDir</code> is <code>null</code> is un-specified, in future versions this will fail due to NPE)
+   */
   public SolrResourceLoader(Path instanceDir) {
     this(instanceDir, null);
   }
@@ -161,11 +171,13 @@ public class SolrResourceLoader implements ResourceLoader, Closeable, SolrClassL
    * otherwise it will attempt to resolve resources using any jar files
    * found in the "lib/" directory in the specified instance directory.
    *
-   * @param instanceDir - base directory for this resource loader, if null locateSolrHome() will be used.
+   * @param instanceDir - base directory for this resource loader, if null locateSolrHome() will be used. (in future versions this will fail due to NPE)
    * @see SolrPaths#locateSolrHome()
    */
   public SolrResourceLoader(Path instanceDir, ClassLoader parent) {
     if (instanceDir == null) {
+      log.warn("SolrResourceLoader created with null instanceDir.  This will not be supported in Solr 9.0");
+
       this.instanceDir = SolrPaths.locateSolrHome();
       log.debug("new SolrResourceLoader for deduced Solr Home: '{}'", this.instanceDir);
     } else {
diff --git a/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java b/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
index cd0ca7e..6d8cb92 100644
--- a/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
+++ b/solr/core/src/java/org/apache/solr/core/XmlConfigFile.java
@@ -110,10 +110,9 @@ public class XmlConfigFile { // formerly simply "Config"
    */
   public XmlConfigFile(SolrResourceLoader loader, String name, InputSource is, String prefix, Properties substituteProps) throws ParserConfigurationException, IOException, SAXException
   {
-    if( loader == null ) {
-      loader = new SolrResourceLoader(SolrPaths.locateSolrHome());
-    }
+    if (null == loader) throw new NullPointerException("loader");
     this.loader = loader;
+    
     this.substituteProperties = substituteProps;
     this.name = name;
     this.prefix = (prefix != null && !prefix.endsWith("/"))? prefix + '/' : prefix;
diff --git a/solr/core/src/java/org/apache/solr/search/SolrCoreParser.java b/solr/core/src/java/org/apache/solr/search/SolrCoreParser.java
index 23d3a93..9d6e038 100755
--- a/solr/core/src/java/org/apache/solr/search/SolrCoreParser.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrCoreParser.java
@@ -44,11 +44,13 @@ public class SolrCoreParser extends CoreParser implements NamedListInitializedPl
 
   protected final SolrQueryRequest req;
 
-  public SolrCoreParser(String defaultField, Analyzer analyzer,
-      SolrQueryRequest req) {
+  public SolrCoreParser(String defaultField, Analyzer analyzer, SolrQueryRequest req) {
     super(defaultField, analyzer);
     queryFactory.addBuilder("LegacyNumericRangeQuery", new LegacyNumericRangeQueryBuilder());
     this.req = req;
+    if (null == req) {
+      throw new NullPointerException("req must not be null");
+    }
   }
 
   @Override
@@ -57,12 +59,7 @@ public class SolrCoreParser extends CoreParser implements NamedListInitializedPl
     if (initArgs == null || initArgs.size() == 0) {
       return;
     }
-    final SolrResourceLoader loader;
-    if (req == null) {
-      loader = new SolrResourceLoader();
-    } else {
-      loader = req.getCore().getResourceLoader();
-    }
+    final SolrResourceLoader loader = req.getCore().getResourceLoader();
 
     final Iterable<Map.Entry<String,Object>> args = initArgs;
     for (final Map.Entry<String,Object> entry : args) {
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index e29b016..156d967 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -184,10 +184,8 @@ public class SolrDispatchFilter extends BaseSolrFilter {
           excludePatterns.add(Pattern.compile(element));
         }
       }
-      
-      String solrHome = (String) config.getServletContext().getAttribute(SOLRHOME_ATTRIBUTE);
-      final Path solrHomePath = solrHome == null ? SolrPaths.locateSolrHome() : Paths.get(solrHome);
-      coresInit = createCoreContainer(solrHomePath, extraProperties);
+
+      coresInit = createCoreContainer(computeSolrHome(config), extraProperties);
       this.httpClient = coresInit.getUpdateShardHandler().getDefaultHttpClient();
       setupJvmMetrics(coresInit);
       
@@ -291,6 +289,14 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   }
 
   /**
+   * Returns the effective Solr Home to use for this node
+   */
+  private static Path computeSolrHome(FilterConfig config) {
+    final String solrHome = (String) config.getServletContext().getAttribute(SOLRHOME_ATTRIBUTE);
+    return (solrHome == null ? SolrPaths.locateSolrHome() : Paths.get(solrHome));
+  }
+  
+  /**
    * Override this to change CoreContainer initialization
    * @return a CoreContainer to hold this server's cores
    */
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
index 4a5346c..0fff339 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
@@ -1411,7 +1411,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
     CoreContainer mockAlwaysUpCoreContainer = mock(CoreContainer.class,
         Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
     when(mockAlwaysUpCoreContainer.isShutDown()).thenReturn(testDone);  // Allow retry on session expiry
-    when(mockAlwaysUpCoreContainer.getResourceLoader()).thenReturn(new SolrResourceLoader());
+    when(mockAlwaysUpCoreContainer.getResourceLoader()).thenReturn(new SolrResourceLoader(createTempDir()));
     ClusterSingletons singletons = new ClusterSingletons(() -> true, r -> r.run());
     // don't wait for all singletons
     singletons.setReady();
diff --git a/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java b/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java
index 2169cc4..366e499 100644
--- a/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java
+++ b/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java
@@ -50,8 +50,9 @@ import static org.hamcrest.core.Is.is;
 public class ResourceLoaderTest extends SolrTestCaseJ4 {
 
   public void testInstanceDir() throws Exception {
-    try (SolrResourceLoader loader = new SolrResourceLoader()) {
-      assertThat(loader.getInstancePath(), is(Paths.get("solr").toAbsolutePath()));
+    final Path dir = createTempDir();
+    try (SolrResourceLoader loader = new SolrResourceLoader(dir.toAbsolutePath())) {
+      assertThat(loader.getInstancePath(), is(dir.toAbsolutePath()));
     }
   }
 
@@ -213,7 +214,7 @@ public class ResourceLoaderTest extends SolrTestCaseJ4 {
   public void testCacheWrongType() throws Exception {
     clearCache();
 
-    SolrResourceLoader loader = new SolrResourceLoader();
+    SolrResourceLoader loader = new SolrResourceLoader(TEST_PATH().resolve("collection1"));
     @SuppressWarnings({"rawtypes"})
     Class[] params = { Map.class };
     Map<String,String> args = Map.of("minGramSize", "1", "maxGramSize", "2");
diff --git a/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java b/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
index d05a917..9d0b15a 100644
--- a/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
+++ b/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
@@ -85,6 +85,28 @@ public class TestCoreContainer extends SolrTestCaseJ4 {
     return ret;
   }
 
+  public void testSolrHomeAndResourceLoader() throws Exception {
+    // regardless of what sys prop may be set, the CoreContainer's init arg should be the definitive
+    // solr home -- and nothing i nthe call stack should be "setting" the sys prop to make that work...
+    final Path fakeSolrHome = createTempDir().toAbsolutePath();
+    System.setProperty(SOLR_HOME_PROP, fakeSolrHome.toString());
+    final Path realSolrHome = createTempDir().toAbsolutePath();
+    final CoreContainer cc = init(realSolrHome, CONFIGSETS_SOLR_XML);
+    try {
+
+      // instance dir & resource loader for the CC
+      assertEquals(realSolrHome.toString(), cc.getSolrHome());
+      assertEquals(realSolrHome, cc.getResourceLoader().getInstancePath());
+
+    } finally {
+      cc.shutdown();
+    }
+    assertEquals("Nothing in solr should be overriding the solr home sys prop in order to work!",
+                 fakeSolrHome.toString(),
+                 System.getProperty(SOLR_HOME_PROP));
+  }
+
+  
   @Test
   public void testShareSchema() throws Exception {
     System.setProperty("shareSchema", "true");
diff --git a/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java b/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
index 5c5ba8f..65d1f41 100644
--- a/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
+++ b/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
@@ -55,7 +55,6 @@ public class TestCoreDiscovery extends SolrTestCaseJ4 {
   private final Path solrHomeDirectory = createTempDir();
 
   private void setMeUp(String alternateCoreDir) throws Exception {
-    System.setProperty("solr.solr.home", solrHomeDirectory.toAbsolutePath().toString());
     String xmlStr = SOLR_XML;
     if (alternateCoreDir != null) {
       xmlStr = xmlStr.replace("<solr>", "<solr> <str name=\"coreRootDirectory\">" + alternateCoreDir + "</str> ");
@@ -114,7 +113,7 @@ public class TestCoreDiscovery extends SolrTestCaseJ4 {
   }
 
   private CoreContainer init() throws Exception {
-    final CoreContainer container = new CoreContainer(SolrPaths.locateSolrHome(), new Properties());
+    final CoreContainer container = new CoreContainer(solrHomeDirectory, new Properties());
     try {
       container.load();
     } catch (Exception e) {
diff --git a/solr/core/src/test/org/apache/solr/index/WrapperMergePolicyFactoryTest.java b/solr/core/src/test/org/apache/solr/index/WrapperMergePolicyFactoryTest.java
index 16be62c..699c4df 100644
--- a/solr/core/src/test/org/apache/solr/index/WrapperMergePolicyFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/index/WrapperMergePolicyFactoryTest.java
@@ -27,7 +27,7 @@ import org.apache.solr.schema.IndexSchema;
 /** Unit tests for {@link WrapperMergePolicyFactory}. */
 public class WrapperMergePolicyFactoryTest extends SolrTestCaseJ4 {
 
-  private final SolrResourceLoader resourceLoader = new SolrResourceLoader();
+  private final SolrResourceLoader resourceLoader = new SolrResourceLoader(createTempDir());
 
   public void testReturnsDefaultMergePolicyIfNoneSpecified() {
     final MergePolicyFactoryArgs args = new MergePolicyFactoryArgs();
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
index 1a2c79c..91ec618 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
@@ -177,59 +177,61 @@ public class SolrMetricManagerTest extends SolrTestCaseJ4 {
   @Test
   public void testReporters() throws Exception {
 
-    SolrResourceLoader loader = new SolrResourceLoader();
-    SolrMetricManager metricManager = new SolrMetricManager();
+    try (SolrResourceLoader loader = new SolrResourceLoader(createTempDir())) {
+      SolrMetricManager metricManager = new SolrMetricManager();
 
-    PluginInfo[] plugins = new PluginInfo[] {
+      PluginInfo[] plugins = new PluginInfo[] {
         createPluginInfo("universal_foo", null, null),
         createPluginInfo("multigroup_foo", "jvm, node, core", null),
         createPluginInfo("multiregistry_foo", null, "solr.node, solr.core.collection1"),
         createPluginInfo("specific_foo", null, "solr.core.collection1"),
         createPluginInfo("node_foo", "node", null),
         createPluginInfo("core_foo", "core", null)
-    };
-    String tag = "xyz";
-    metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.node);
-    Map<String, SolrMetricReporter> reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
-    assertEquals(4, reporters.size());
-    assertTrue(reporters.containsKey("universal_foo@" + tag));
-    assertTrue(reporters.containsKey("multigroup_foo@" + tag));
-    assertTrue(reporters.containsKey("node_foo@" + tag));
-    assertTrue(reporters.containsKey("multiregistry_foo@" + tag));
-
-    metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.core, "collection1");
-    reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1"));
-    assertEquals(5, reporters.size());
-    assertTrue(reporters.containsKey("universal_foo@" + tag));
-    assertTrue(reporters.containsKey("multigroup_foo@" + tag));
-    assertTrue(reporters.containsKey("specific_foo@" + tag));
-    assertTrue(reporters.containsKey("core_foo@" + tag));
-    assertTrue(reporters.containsKey("multiregistry_foo@" + tag));
-
-    metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.jvm);
-    reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
-    assertEquals(2, reporters.size());
-    assertTrue(reporters.containsKey("universal_foo@" + tag));
-    assertTrue(reporters.containsKey("multigroup_foo@" + tag));
-
-    metricManager.removeRegistry("solr.jvm");
-    reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
-    assertEquals(0, reporters.size());
-
-    metricManager.removeRegistry("solr.node");
-    reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
-    assertEquals(0, reporters.size());
-
-    metricManager.removeRegistry("solr.core.collection1");
-    reporters = metricManager.getReporters(
-        SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1"));
-    assertEquals(0, reporters.size());
-
+      };
+      String tag = "xyz";
+      metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.node);
+      Map<String, SolrMetricReporter> reporters = metricManager.getReporters
+        (SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
+          
+      assertEquals(4, reporters.size());
+      assertTrue(reporters.containsKey("universal_foo@" + tag));
+      assertTrue(reporters.containsKey("multigroup_foo@" + tag));
+      assertTrue(reporters.containsKey("node_foo@" + tag));
+      assertTrue(reporters.containsKey("multiregistry_foo@" + tag));
+      
+      metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.core, "collection1");
+      reporters = metricManager.getReporters
+        (SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1"));
+          
+      assertEquals(5, reporters.size());
+      assertTrue(reporters.containsKey("universal_foo@" + tag));
+      assertTrue(reporters.containsKey("multigroup_foo@" + tag));
+      assertTrue(reporters.containsKey("specific_foo@" + tag));
+      assertTrue(reporters.containsKey("core_foo@" + tag));
+      assertTrue(reporters.containsKey("multiregistry_foo@" + tag));
+      
+      metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.jvm);
+      reporters = metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
+                                             
+      assertEquals(2, reporters.size());
+      assertTrue(reporters.containsKey("universal_foo@" + tag));
+      assertTrue(reporters.containsKey("multigroup_foo@" + tag));
+      
+      metricManager.removeRegistry("solr.jvm");
+      reporters = metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
+                                             
+      assertEquals(0, reporters.size());
+      
+      metricManager.removeRegistry("solr.node");
+      reporters = metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
+                                             
+      assertEquals(0, reporters.size());
+      
+      metricManager.removeRegistry("solr.core.collection1");
+      reporters = metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1"));
+                                             
+      assertEquals(0, reporters.size());
+    }
   }
 
   @Test
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java b/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
index 7a0e519..d82abdb 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
@@ -37,20 +37,24 @@ import org.apache.lucene.search.spans.SpanNearQuery;
 import org.apache.lucene.search.spans.SpanOrQuery;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanTermQuery;
-import org.apache.solr.SolrTestCase;
+import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.request.SolrQueryRequest;
+import org.junit.BeforeClass;
 
-public class TestSolrCoreParser extends SolrTestCase {
+public class TestSolrCoreParser extends SolrTestCaseJ4 {
 
+  @BeforeClass
+  public static void init() throws Exception {
+    initCore("solrconfig.xml","schema.xml");
+  }
+  
   private SolrCoreParser solrCoreParser;
 
   private CoreParser solrCoreParser() {
     if (solrCoreParser == null) {
       final String defaultField = "contents";
       final Analyzer analyzer = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, true, MockTokenFilter.ENGLISH_STOPSET);
-      final SolrQueryRequest req = null;
-      solrCoreParser = new SolrCoreParser(defaultField, analyzer, req);
+      solrCoreParser = new SolrCoreParser(defaultField, analyzer, req());
       {
         final NamedList<String> args = new NamedList<>();
         args.add("HelloQuery", HelloQueryBuilder.class.getCanonicalName());
diff --git a/solr/core/src/test/org/apache/solr/search/TestXmlQParser.java b/solr/core/src/test/org/apache/solr/search/TestXmlQParser.java
index 76ed752..79207f0 100644
--- a/solr/core/src/test/org/apache/solr/search/TestXmlQParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestXmlQParser.java
@@ -21,18 +21,32 @@ import java.lang.invoke.MethodHandles;
 import org.apache.lucene.queryparser.xml.CoreParser;
 
 import org.apache.lucene.queryparser.xml.TestCoreParser;
+
 import org.apache.solr.util.StartupLoggingUtils;
+import org.apache.solr.util.TestHarness;
+
 import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 public class TestXmlQParser extends TestCoreParser {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private CoreParser solrCoreParser;
-
+  private static TestHarness harness;
+    
+  @BeforeClass
+  public static void init() throws Exception {
+    // we just need to stub this out so we can construct a SolrCoreParser
+    harness = new TestHarness(TestHarness.buildTestNodeConfig(createTempDir()));
+  }
+  
   @AfterClass
   public static void shutdownLogger() throws Exception {
+    harness.close();
+    harness = null;
     StartupLoggingUtils.shutdown();
   }
 
@@ -42,7 +56,7 @@ public class TestXmlQParser extends TestCoreParser {
       solrCoreParser = new SolrCoreParser(
           super.defaultField(),
           super.analyzer(),
-          null);
+          harness.getRequestFactory("/select", 0, 0).makeRequest());
     }
     return solrCoreParser;
   }
diff --git a/solr/core/src/test/org/apache/solr/security/MultiDestinationAuditLoggerTest.java b/solr/core/src/test/org/apache/solr/security/MultiDestinationAuditLoggerTest.java
index 6b3a51f..d20b6dd 100644
--- a/solr/core/src/test/org/apache/solr/security/MultiDestinationAuditLoggerTest.java
+++ b/solr/core/src/test/org/apache/solr/security/MultiDestinationAuditLoggerTest.java
@@ -17,6 +17,7 @@
 package org.apache.solr.security;
 
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -48,7 +49,7 @@ public class MultiDestinationAuditLoggerTest extends SolrTestCaseJ4 {
     plugins.add(conf2);
     config.put("plugins", plugins);
 
-    SolrResourceLoader loader = new SolrResourceLoader();
+    SolrResourceLoader loader = new SolrResourceLoader(Paths.get(""));
     al.inform(loader);
     al.init(config);
 
@@ -79,4 +80,4 @@ public class MultiDestinationAuditLoggerTest extends SolrTestCaseJ4 {
     assertEquals(1, config.size());
     al.close();
   }
-}
\ No newline at end of file
+}
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
index 174b24a..7cfaaff 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
@@ -21,6 +21,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
 import java.time.Instant;
 import java.util.Date;
 import java.util.List;
@@ -49,7 +50,7 @@ public class QueryResponseTest extends SolrTestCase {
   public void testRangeFacets() throws Exception {
     XMLResponseParser parser = new XMLResponseParser();
     NamedList<Object> response = null;
-    try (SolrResourceLoader loader = new SolrResourceLoader();
+    try (SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
          InputStream is = loader.openResource("solrj/sampleRangeFacetResponse.xml")) {
       assertNotNull(is);
 
@@ -111,7 +112,7 @@ public class QueryResponseTest extends SolrTestCase {
   public void testGroupResponse() throws Exception {
     XMLResponseParser parser = new XMLResponseParser();
     NamedList<Object> response = null;
-    try (SolrResourceLoader loader = new SolrResourceLoader();
+    try (SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
          InputStream is = loader.openResource("solrj/sampleGroupResponse.xml")) {
       assertNotNull(is);
       try (Reader in = new InputStreamReader(is, StandardCharsets.UTF_8)) {
@@ -218,7 +219,7 @@ public class QueryResponseTest extends SolrTestCase {
     XMLResponseParser parser = new XMLResponseParser();
     NamedList<Object> response = null;
 
-    try (SolrResourceLoader loader = new SolrResourceLoader();
+    try (SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
          InputStream is = loader.openResource("solrj/sampleSimpleGroupResponse.xml")) {
       assertNotNull(is);
       try (Reader in = new InputStreamReader(is, StandardCharsets.UTF_8)) {
@@ -262,7 +263,7 @@ public class QueryResponseTest extends SolrTestCase {
   // commented out on: 24-Dec-2018   @BadApple(bugUrl="https://issues.apache.org/jira/browse/SOLR-12028") // added 20-Sep-2018
   public void testIntervalFacetsResponse() throws Exception {
     XMLResponseParser parser = new XMLResponseParser();
-    try(SolrResourceLoader loader = new SolrResourceLoader()) {
+    try(SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath())) {
       InputStream is = loader.openResource("solrj/sampleIntervalFacetsResponse.xml");
       assertNotNull(is);
       Reader in = new InputStreamReader(is, StandardCharsets.UTF_8);
@@ -308,7 +309,7 @@ public class QueryResponseTest extends SolrTestCase {
     XMLResponseParser parser = new XMLResponseParser();
     NamedList<Object> response;
 
-    try (SolrResourceLoader loader = new SolrResourceLoader();
+    try (SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
          InputStream is = loader.openResource("solrj/sampleDebugResponse.xml")) {
           assertNotNull(is);
       try (Reader in = new InputStreamReader(is, StandardCharsets.UTF_8)) {
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestClusteringResponse.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestClusteringResponse.java
index 5dd3ab3..1c52035 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestClusteringResponse.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestClusteringResponse.java
@@ -19,6 +19,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
 
@@ -40,7 +41,7 @@ public class TestClusteringResponse extends SolrJettyTestBase {
     NamedList<Object> response = null;
 
     /*Load a simple XML with the clustering response encoded in an XML format*/
-    try (SolrResourceLoader loader = new SolrResourceLoader();
+    try (SolrResourceLoader loader = new SolrResourceLoader(Paths.get("").toAbsolutePath());
          InputStream is = loader.openResource("solrj/sampleClusteringResponse.xml")) {
       assertNotNull(is);
       try (Reader in = new InputStreamReader(is, StandardCharsets.UTF_8)) {
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java b/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
index 1a72981..6b27e5e 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
@@ -25,6 +25,7 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
@@ -47,7 +48,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
 
   public void testFileStream() throws IOException {
     File file = new File(createTempDir().toFile(), "README");
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file)) {
       assertNotNull(is);
       IOUtils.copy(is, os);
@@ -70,7 +72,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
   public void testFileStreamGZIP() throws IOException {
     File file = new File(createTempDir().toFile(), "README.gz");
 
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file);
          GZIPOutputStream zos = new GZIPOutputStream(os)) {
       IOUtils.copy(is, zos);
@@ -95,7 +98,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
   public void testURLStream() throws IOException {
     File file = new File(createTempDir().toFile(), "README");
 
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file)) {
       IOUtils.copy(is, os);
     }
@@ -124,7 +128,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
   public void testURLStreamGZIP() throws IOException {
     File file = new File(createTempDir().toFile(), "README.gz");
 
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file);
          GZIPOutputStream zos = new GZIPOutputStream(os)) {
       IOUtils.copy(is, zos);
@@ -149,7 +154,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
   public void testURLStreamCSVGZIPExtention() throws IOException {
     File file = new File(createTempDir().toFile(), "README.CSV.gz");
 
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file);
          GZIPOutputStream zos = new GZIPOutputStream(os)) {
       IOUtils.copy(is, zos);
@@ -174,7 +180,8 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
   public void testURLStreamJSONGZIPExtention() throws IOException {
     File file = new File(createTempDir().toFile(), "README.json.gzip");
 
-    try (SolrResourceLoader srl = new SolrResourceLoader(); InputStream is = srl.openResource("solrj/README");
+    try (SolrResourceLoader srl = new SolrResourceLoader(Paths.get("").toAbsolutePath());
+         InputStream is = srl.openResource("solrj/README");
          FileOutputStream os = new FileOutputStream(file);
          GZIPOutputStream zos = new GZIPOutputStream(os)) {
       IOUtils.copy(is, zos);
diff --git a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
index a2f8177..2f18f26 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -43,7 +44,6 @@ import org.apache.solr.core.NodeConfig;
 import org.apache.solr.core.PluginInfo;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrCore;
-import org.apache.solr.core.SolrPaths;
 import org.apache.solr.core.SolrXmlConfig;
 import org.apache.solr.handler.UpdateRequestHandler;
 import org.apache.solr.metrics.reporters.SolrJmxReporter;
@@ -133,6 +133,19 @@ public class TestHarness extends BaseTestHarness {
       this(SolrTestCaseJ4.DEFAULT_TEST_CORENAME, dataDirectory, solrConfig, indexSchema);
   }
 
+  /** 
+   * Helper method to let us do some home sys prop check in delegated construtor.
+   * in "real" code SolrDispatchFilter takes care of checking this sys prop when building NodeConfig/CoreContainer
+   */
+  private static Path checkAndReturnSolrHomeSysProp() {
+    final String SOLR_HOME = "solr.solr.home";
+    final String home = System.getProperty(SOLR_HOME);
+    if (null == home) {
+      throw new IllegalStateException("This TestHarness constructor requires " + SOLR_HOME + " sys prop to be set by test first");
+    }
+    return Paths.get(home).toAbsolutePath().normalize();
+  }
+  
   /**
    * @param coreName to initialize
    * @param dataDir path for index data, will not be cleaned up
@@ -140,7 +153,7 @@ public class TestHarness extends BaseTestHarness {
    * @param indexSchema schema resource name
    */
   public TestHarness(String coreName, String dataDir, String solrConfig, String indexSchema) {
-    this(buildTestNodeConfig(SolrPaths.locateSolrHome()),
+    this(buildTestNodeConfig(checkAndReturnSolrHomeSysProp()),
         new TestCoresLocator(coreName, dataDir, solrConfig, indexSchema));
     this.coreName = (coreName == null) ? SolrTestCaseJ4.DEFAULT_TEST_CORENAME : coreName;
   }
diff --git a/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java b/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
index 37a2bfb..ed88f0b 100644
--- a/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
+++ b/solr/test-framework/src/test/org/apache/solr/cloud/MiniSolrCloudClusterTest.java
@@ -19,6 +19,7 @@ package org.apache.solr.cloud;
 
 import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.Properties;
 
@@ -27,6 +28,8 @@ import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.embedded.JettyConfig;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.core.SolrCore;
 import org.apache.solr.util.RevertDefaultThreadHandlerRule;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -99,6 +102,39 @@ public class MiniSolrCloudClusterTest extends SolrTestCaseJ4 {
     cluster.shutdown();
   }
 
+  public void testSolrHomeAndResourceLoaders() throws Exception {
+    final String SOLR_HOME_PROP = "solr.solr.home";
+    // regardless of what sys prop may be set, everything in the cluster should use solr home dirs under the 
+    // configured base dir -- and nothing in the call stack should be "setting" the sys prop to make that work...
+    final String fakeSolrHome = createTempDir().toAbsolutePath().toString();
+    System.setProperty(SOLR_HOME_PROP, fakeSolrHome);
+
+    // mock FS from createTempDir don't play nice using 'startsWith' when the solr stack reconsistutes the path from string
+    // so we have to go the string route here as well...
+    final Path workDir = Paths.get(createTempDir().toAbsolutePath().toString());
+    
+    final MiniSolrCloudCluster cluster = new MiniSolrCloudCluster(1, workDir, JettyConfig.builder().build());
+    try {
+      final JettySolrRunner jetty = cluster.getJettySolrRunners().get(0);
+      assertTrue(jetty.getCoreContainer().getSolrHome() + " vs " + workDir,
+                 // mock dirs from createTempDir() don't play nice with startsWith, so we have to use the string value
+                 Paths.get(jetty.getCoreContainer().getSolrHome()).startsWith(workDir));
+      assertEquals(jetty.getCoreContainer().getSolrHome(),
+                   jetty.getCoreContainer().getResourceLoader().getInstancePath().toAbsolutePath().toString());
+
+      assertTrue(CollectionAdminRequest.createCollection("test", 1,1).process(cluster.getSolrClient()).isSuccess());
+      final SolrCore core = jetty.getCoreContainer().getCores().get(0);
+      assertTrue(core.getInstancePath() + " vs " + workDir,
+                 core.getInstancePath().startsWith(workDir));
+      assertEquals(core.getInstancePath(),
+                   core.getResourceLoader().getInstancePath());
+    } finally {
+      cluster.shutdown();
+    }
+    assertEquals("There is no reason why anything should have set this sysprop",
+                 fakeSolrHome, System.getProperty(SOLR_HOME_PROP));
+  }
+  
   public void testMultipleClustersDiffZk() throws Exception {
     final MiniSolrCloudCluster x = new MiniSolrCloudCluster(1, createTempDir(), JettyConfig.builder().build());
     try {