SOLR-7171: BaseDistributedSearchTestCase now clones getSolrHome() for each subclass, and consistently uses getSolrXml()

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1663381 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index a10fbb1..1cfc0ac 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -172,6 +172,9 @@
 * SOLR-7178: OverseerAutoReplicaFailoverThread compares Integer objects using ==
   (shalin)
 
+* SOLR-7171: BaseDistributedSearchTestCase now clones getSolrHome() for each subclass, 
+  and consistently uses getSolrXml().  (hossman)
+
 Optimizations
 ----------------------
 
diff --git a/solr/contrib/clustering/src/test-files/log4j.properties b/solr/contrib/clustering/src/test-files/log4j.properties
new file mode 100644
index 0000000..9b74a5f
--- /dev/null
+++ b/solr/contrib/clustering/src/test-files/log4j.properties
@@ -0,0 +1,10 @@
+#  Logging level
+log4j.rootLogger=INFO, CONSOLE
+
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Target=System.err
+log4j.appender.CONSOLE.layout=org.apache.solr.util.SolrLogLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-5p - %d{yyyy-MM-dd HH:mm:ss.SSS}; %C; %m\n
+
+log4j.logger.org.apache.zookeeper=WARN
+log4j.logger.org.apache.hadoop=WARN
diff --git a/solr/core/src/test/org/apache/solr/TestSimpleTrackingShardHandler.java b/solr/core/src/test/org/apache/solr/TestSimpleTrackingShardHandler.java
new file mode 100644
index 0000000..d2d43ee
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/TestSimpleTrackingShardHandler.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.handler.component.TrackingShardHandlerFactory;
+import org.apache.solr.handler.component.TrackingShardHandlerFactory.ShardRequestAndParams;
+import org.apache.solr.handler.component.TrackingShardHandlerFactory.RequestTrackingQueue;
+
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * super simple sanity check that SimpleTrackingShardHandler can be used in a 
+ * {@link BaseDistributedSearchTestCase} subclass
+ */
+public class TestSimpleTrackingShardHandler extends BaseDistributedSearchTestCase {
+
+  @Override
+  protected String getSolrXml() {
+    return "solr-trackingshardhandler.xml";
+  }
+
+  public void testSolrXmlOverrideAndCorrectShardHandler() throws Exception {
+    RequestTrackingQueue trackingQueue = new RequestTrackingQueue();
+    
+    TrackingShardHandlerFactory.setTrackingQueue(jettys, trackingQueue);
+    // sanity check that our control jetty has the correct configs as well
+    TrackingShardHandlerFactory.setTrackingQueue(Collections.singletonList(controlJetty), trackingQueue);
+    
+    QueryResponse ignored = query("q","*:*", "fl", "id", "sort", "id asc");
+
+    int numShardRequests = 0;
+    for (List<ShardRequestAndParams> shard : trackingQueue.getAllRequests().values()) {
+      for (ShardRequestAndParams shardReq : shard) {
+        numShardRequests++;
+      }
+    }
+    TrackingShardHandlerFactory.setTrackingQueue(jettys, null);
+    TrackingShardHandlerFactory.setTrackingQueue(Collections.singletonList(controlJetty), null);
+  }
+}
diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 3fdf077..20eea63 100644
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -54,6 +54,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -306,9 +307,12 @@
   }
 
   protected JettySolrRunner createControlJetty() throws Exception {
-    writeCoreProperties(testDir.toPath().resolve("control/cores"), DEFAULT_TEST_CORENAME);
-    System.setProperty("coreRootDirectory", testDir.toPath().resolve("control").toString());
-    JettySolrRunner jetty = createJetty(new File(getSolrHome()), testDir + "/control/data", null, getSolrConfigFile(), getSchemaFile());
+    Path jettyHome = testDir.toPath().resolve("control");
+    File jettyHomeFile = jettyHome.toFile();
+    seedSolrHome(jettyHomeFile);
+    seedCoreRootDirWithDefaultTestCore(jettyHome);
+    System.setProperty("coreRootDirectory", jettyHome.toString());
+    JettySolrRunner jetty = createJetty(jettyHomeFile, null, null, getSolrConfigFile(), getSchemaFile());
     return jetty;
   }
 
@@ -323,13 +327,14 @@
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < numShards; i++) {
       if (sb.length() > 0) sb.append(',');
-      String shardname = "shard" + i;
-      Path coresPath = testDir.toPath().resolve(shardname).resolve("cores");
-      writeCoreProperties(coresPath, DEFAULT_TEST_CORENAME);
-      System.setProperty("coreRootDirectory", testDir.toPath().resolve(shardname).toString());
-      JettySolrRunner j = createJetty(new File(getSolrHome()),
-          testDir + "/shard" + i + "/data", null, getSolrConfigFile(),
-          getSchemaFile());
+      final String shardname = "shard" + i;
+      Path jettyHome = testDir.toPath().resolve(shardname);
+      File jettyHomeFile = jettyHome.toFile();
+      seedSolrHome(jettyHomeFile);
+      seedCoreRootDirWithDefaultTestCore(jettyHome);
+      System.setProperty("coreRootDirectory", jettyHome.toString());
+      JettySolrRunner j = createJetty(jettyHomeFile, null, null, getSolrConfigFile(), getSchemaFile());
+                                      
       jettys.add(j);
       clients.add(createNewSolrClient(j.getLocalPort()));
       String shardStr = buildUrl(j.getLocalPort()) + "/" + DEFAULT_TEST_CORENAME;
@@ -1041,12 +1046,38 @@
     return null;
   }
   
-  protected void setupJettySolrHome(File jettyHome) throws IOException {
+  /**
+   * Given a directory that will be used as the SOLR_HOME for a jetty instance, seeds that 
+   * directory with the contents of {@link #getSolrHome} and ensures that the proper {@link #getSolrXml} 
+   * file is in place.
+   */
+  private void seedSolrHome(File jettyHome) throws IOException {
     FileUtils.copyDirectory(new File(getSolrHome()), jettyHome);
     String solrxml = getSolrXml();
     if (solrxml != null) {
       FileUtils.copyFile(new File(getSolrHome(), solrxml), new File(jettyHome, "solr.xml"));
     }
+  }
+
+  /**
+   * Given a directory that will be used as the <code>coreRootDirectory</code> for a jetty instance, 
+   * Creates a core directory named {@link #DEFAULT_TEST_CORENAME} using a trivial
+   * <code>core.properties</code> if this file does not already exist.
+   *
+   * @see #writeCoreProperties(Path,String)
+   * @see #CORE_PROPERTIES_FILENAME
+   */
+  private void seedCoreRootDirWithDefaultTestCore(Path coreRootDirectory) throws IOException {
+    // Kludgy and brittle with assumptions about writeCoreProperties, but i don't want to 
+    // try to change the semantics of that method to ignore existing files
+    Path coreDir = coreRootDirectory.resolve(DEFAULT_TEST_CORENAME);
+    if (Files.notExists(coreDir.resolve(CORE_PROPERTIES_FILENAME))) {
+      writeCoreProperties(coreDir, DEFAULT_TEST_CORENAME);
+    } // else nothing to do, DEFAULT_TEST_CORENAME already exists
+  }
+
+  protected void setupJettySolrHome(File jettyHome) throws IOException {
+    seedSolrHome(jettyHome);
 
     Properties coreProperties = new Properties();
     coreProperties.setProperty("name", "collection1");
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 ae37a1c..2026ff7 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -133,6 +133,7 @@
 public abstract class SolrTestCaseJ4 extends LuceneTestCase {
 
   public static final String DEFAULT_TEST_CORENAME = "collection1";
+  protected static final String CORE_PROPERTIES_FILENAME = "core.properties";
 
   private static String coreName = DEFAULT_TEST_CORENAME;
 
@@ -152,7 +153,7 @@
     log.info("Writing core.properties file to {}", coreDirectory);
     Files.createDirectories(coreDirectory);
     try (Writer writer =
-             new OutputStreamWriter(Files.newOutputStream(coreDirectory.resolve("core.properties")), Charset.forName("UTF-8"))) {
+             new OutputStreamWriter(Files.newOutputStream(coreDirectory.resolve(CORE_PROPERTIES_FILENAME)), Charset.forName("UTF-8"))) {
       properties.store(writer, testname);
     }
   }
diff --git a/solr/test-framework/src/java/org/apache/solr/handler/component/TrackingShardHandlerFactory.java b/solr/test-framework/src/java/org/apache/solr/handler/component/TrackingShardHandlerFactory.java
index 0ffb1ea..a000750 100644
--- a/solr/test-framework/src/java/org/apache/solr/handler/component/TrackingShardHandlerFactory.java
+++ b/solr/test-framework/src/java/org/apache/solr/handler/component/TrackingShardHandlerFactory.java
@@ -155,7 +155,7 @@
     for (JettySolrRunner runner : runners) {
       CoreContainer container = ((SolrDispatchFilter) runner.getDispatchFilter().getFilter()).getCores();
       ShardHandlerFactory factory = container.getShardHandlerFactory();
-      assert factory instanceof TrackingShardHandlerFactory;
+      assert factory instanceof TrackingShardHandlerFactory : "not a TrackingShardHandlerFactory: " + factory.getClass();
       TrackingShardHandlerFactory trackingShardHandlerFactory = (TrackingShardHandlerFactory) factory;
       trackingShardHandlerFactory.setTrackingQueue(queue);
     }