Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package org.apache.solr.cloud;
   
   /*
    * 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.
   */
  
  import static org.apache.solr.cloud.OverseerCollectionProcessor.CREATE_NODE_SET;
  import static org.apache.solr.cloud.OverseerCollectionProcessor.NUM_SLICES;
  import static org.apache.solr.cloud.OverseerCollectionProcessor.SHARDS_PROP;
  import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
  import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
  
  import java.io.File;
  import java.net.URI;
  import java.net.URL;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Random;
  import java.util.Set;
  
  import org.junit.After;
  import org.junit.Before;
  import org.slf4j.Logger;
TODO: we should still test this works as a custom update chain as well as what we test now - the default update chain
  
  @Slow
  public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTestBase {
    static Logger log = LoggerFactory.getLogger(AbstractFullDistribZkTestBase.class);
    
    @BeforeClass
    public static void beforeFullSolrCloudTest() {
      // shorten the log output more for this test type
     if ( != null.setShorterFormat();
   }
   
   public static final String SHARD1 = "shard1";
   public static final String SHARD2 = "shard2";
   
   protected boolean printLayoutOnTearDown = false;
   
   String t1 = "a_t";
   String i1 = "a_si";
   String nint = "n_i";
   String tint = "n_ti";
   String nfloat = "n_f";
   String tfloat = "n_tf";
   String ndouble = "n_d";
   String tdouble = "n_td";
   String nlong = "n_l";
   String tlong = "other_tl1";
   String ndate = "n_dt";
   String tdate = "n_tdt";
   
   String oddField = "oddField_s";
   String missingField = "ignore_exception__missing_but_valid_field_t";
   String invalidField = "ignore_exception__invalid_field_not_in_schema";
   protected int sliceCount;
 
   protected CloudSolrServer controlClientCloud;  // cloud version of the control client
   protected volatile CloudSolrServer cloudClient;
   
   protected List<CloudJettyRunnercloudJettys = new ArrayList<>();
   protected Map<String,List<CloudJettyRunner>> shardToJetty = new HashMap<>();
   private AtomicInteger jettyIntCntr = new AtomicInteger(0);
   protected ChaosMonkey chaosMonkey;
   
   protected Map<String,CloudJettyRunnershardToLeaderJetty = new HashMap<>();
   private boolean cloudInit;
   protected boolean checkCreatedVsState;
   protected boolean useJettyDataDir = true;
 
   protected Map<URI,SocketProxyproxies = new HashMap<URI,SocketProxy>();
   
   public static class CloudJettyRunner {
     public JettySolrRunner jetty;
     public String nodeName;
     public String coreNodeName;
     public String url;
     public CloudSolrServerClient client;
     public ZkNodeProps info;
     @Override
     public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result + (( == null) ? 0 : .hashCode());
       return result;
     }
     @Override
     public boolean equals(Object obj) {
       if (this == objreturn true;
       if (obj == nullreturn false;
       if (getClass() != obj.getClass()) return false;
       CloudJettyRunner other = (CloudJettyRunnerobj;
       if ( == null) {
         if (other.url != nullreturn false;
       } else if (!.equals(other.url)) return false;
       return true;
     }
     @Override
     public String toString() {
       return "CloudJettyRunner [url=" +  + "]";
     }
   }
   
   static class CloudSolrServerClient {
     String shardName;
     int port;
     public ZkNodeProps info;
     
     public CloudSolrServerClient() {}
     
     public CloudSolrServerClient(SolrServer client) {
       this. = client;
     }
     
     @Override
     public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result + (( == null) ? 0 : .hashCode());
       return result;
     }
     
     @Override
     public boolean equals(Object obj) {
       if (this == objreturn true;
       if (obj == nullreturn false;
       if (getClass() != obj.getClass()) return false;
       CloudSolrServerClient other = (CloudSolrServerClientobj;
       if ( == null) {
         if (other.solrClient != nullreturn false;
       } else if (!.equals(other.solrClient)) return false;
       return true;
     }
     
   }
   
   @Before
   public void setUp() throws Exception {
     super.setUp();
     // ignoreException(".*");
     if ( > 0) {
       System.setProperty("numShards", Integer.toString());
     } else {
       System.clearProperty("numShards");
     }
     
     if (isSSLMode()) {
       System.clearProperty("urlScheme");
       ZkStateReader zkStateReader = new ZkStateReader(.getZkAddress(),
       try {
         zkStateReader.getZkClient().create(.,
           ZkStateReader.toJSON(Collections.singletonMap("urlScheme","https")), 
           .true);
       } finally {
         zkStateReader.close();
       }
     }
   }
   
   public static void beforeClass() {
     System.setProperty("solrcloud.update.delay""0");
   }
   
   public static void afterClass() throws Exception {
     System.clearProperty("solrcloud.update.delay");
     System.clearProperty("genericCoreNodeNames");
   }
   
      = true;
     
      = 4;
      = 2;
     // TODO: for now, turn off stress because it uses regular clients, and we
     // need the cloud client because we kill servers
      = 0;
     
   }
   
   protected String getDataDir(String dataDirthrows IOException {
     return dataDir;
   }
   
   protected void initCloud() throws Exception {
     assert( == false);
      = true;
     try {
       
       .connect();
     } catch (MalformedURLException e) {
       throw new RuntimeException(e);
     }
     
     ZkStateReader zkStateReader = .getZkStateReader();
     
      = new ChaosMonkey(zkStateReader,
         );
   }
   
   protected CloudSolrServer createCloudClient(String defaultCollection)
       throws MalformedURLException {
     if (defaultCollection != nullserver.setDefaultCollection(defaultCollection);
     server.getLbServer().getHttpClient().getParams()
     return server;
   }
   
   protected void createServers(int numServersthrows Exception {
     
     System.setProperty("collection""control_collection");
 
     // we want hashes by default for the control, so set to 1 shard as opposed to leaving unset
     String oldNumShards = System.getProperty(.);
     
     try {
       
       File controlJettyDir = createTempDir();
       setupJettySolrHome(controlJettyDir);
       
        = createJetty(controlJettyDir ? getDataDir(
           + "/control/data") : null); // don't pass shard name... let it default to
                                // "shard1"
 
 
       
       if ( <= 0) {
         // for now, just create the cloud client for the control if we don't
         // create the normal cloud client.
         // this can change if more tests need it.
          = createCloudClient("control_collection");
         .connect();
             "control_collection", 0);
         // NOTE: we are skipping creation of the chaos monkey by returning here
          = // temporary - some code needs/uses
                                           // cloudClient
         return;
       }
       
     } finally {
       System.clearProperty("collection");
       if (oldNumShards != null) {
         System.setProperty(.oldNumShards);
       } else {
       }
     }
 
 
     initCloud();
     
     createJettys(numServers).size();
     
     int cnt = getTotalReplicas();
     if (cnt > 0) {
     }
 
   }
 
 
   protected void waitForCollection(ZkStateReader readerString collectionint slicesthrows Exception {
     // wait until shards have started registering...
     int cnt = 30;
     while (!reader.getClusterState().getCollections().contains(collection)) {
       if (cnt == 0) {
         throw new RuntimeException("timeout waiting for collection in cluster state: collection=" + collection);
       }
       cnt--;
       Thread.sleep(500);
     }
     cnt = 30;
     while (reader.getClusterState().getSlices(collection).size() < slices) {
       if (cnt == 0) {
         throw new RuntimeException("timeout waiting for collection shards to come up: collection="+collection
             + ", slices.expected="+slices" slices.actual= " + reader.getClusterState().getSlices(collection).size()
             + " slices : "reader.getClusterState().getSlices(collection) );
       }
       cnt--;
       Thread.sleep(500);
     }
   }
   
   protected List<JettySolrRunnercreateJettys(int numJettysthrows Exception {
     return createJettys(numJettysfalse);
   }
  

  

Parameters:
checkCreatedVsState if true, make sure the number created (numJettys) matches the number in the cluster state - if you add more jetties this may not be the case
 
   protected List<JettySolrRunnercreateJettys(int numJettysboolean checkCreatedVsStatethrows Exception {
     List<JettySolrRunnerjettys = new ArrayList<>();
     List<SolrServerclients = new ArrayList<>();
     StringBuilder sb = new StringBuilder();
     for (int i = 1; i <= numJettysi++) {
       if (sb.length() > 0) sb.append(',');
       int cnt = this..incrementAndGet();
 
       File jettyDir = createTempDir();
 
       jettyDir.mkdirs();
       setupJettySolrHome(jettyDir);
       .info("create jetty " + i); 
       JettySolrRunner j = createJetty(jettyDir ? getDataDir( + "/jetty"
           + cnt) : nullnull"solrconfig.xml"null);
       jettys.add(j);
       SolrServer client = createNewSolrServer(j.getLocalPort());
       clients.add(client);
     }
   
     this..addAll(jettys);
     this..addAll(clients);
     
     int numShards = getTotalReplicas();
     if (checkCreatedVsState) {
       // now wait until we see that the number of shards in the cluster state
       // matches what we expect
       int retries = 0;
       while (numShards != ) {
         numShards = getTotalReplicas();
         if (numShards == break;
         if (retries++ == 60) {
            = true;
           fail("Shards in the state does not match what we set:" + numShards
               + " vs " + );
         }
         Thread.sleep(500);
       }
 
       ZkStateReader zkStateReader = .getZkStateReader();
       // also make sure we have a leader for each shard
       for (int i = 1; i <= i++) {
         zkStateReader.getLeaderRetry("shard" + i, 10000);
       }
     }
 
     if (numShards > 0) {
       updateMappingsFromZk(this.this.);
     }
     
     // build the shard string
     for (int i = 1; i <= numJettys / 2; i++) {
       JettySolrRunner j = this..get(i);
       JettySolrRunner j2 = this..get(i + (numJettys / 2 - 1));
       if (sb.length() > 0) sb.append(',');
       sb.append(buildUrl(j.getLocalPort()));
       sb.append("|").append(buildUrl(j2.getLocalPort()));
     }
      = sb.toString();
     
     return jettys;
   }
 
 
   protected SolrServer startCloudJetty(String collectionString shardthrows Exception {
     // TODO: use the collection string!!!!
     collection = ;
 
     int totalReplicas = getTotalReplicas(collection);
 
 
     int cnt = this..incrementAndGet();
 
       File jettyDir = createTempDir("jetty");
       jettyDir.mkdirs();
       org.apache.commons.io.FileUtils.copyDirectory(new File(getSolrHome()), jettyDir);
       JettySolrRunner j = createJetty(jettyDir + "/jetty" + cntshard"solrconfig.xml"null);
       .add(j);
       SolrServer client = createNewSolrServer(j.getLocalPort());
       .add(client);
 
     int retries = 60;
     while (--retries >= 0) {
       // total replicas changed.. assume it was us
       if (getTotalReplicas(collection) != totalReplicas) {
        break;
       }
       Thread.sleep(500);
     }
 
     if (retries <= 0) {
       fail("Timeout waiting for " + j + " to appear in clusterstate");
       printLayout();
     }
 
     updateMappingsFromZk(this.this.);
     return client;
   }
 
 
   /* Total number of replicas (number of cores serving an index to the collection) shown by the cluster state */
   protected int getTotalReplicas(String collection) {
     ZkStateReader zkStateReader = .getZkStateReader();
     DocCollection coll = zkStateReader.getClusterState().getCollectionOrNull(collection);
     if (coll == nullreturn 0;  // support for when collection hasn't been created yet
     int cnt = 0;
     for (Slice slices : coll.getSlices()) {
       cnt += slices.getReplicas().size();
     }
     return cnt;
   }
   
   public JettySolrRunner createJetty(String dataDirString ulogDirString shardList,
       String solrConfigOverridethrows Exception {
     
     JettySolrRunner jetty = new JettySolrRunner(getSolrHome(), , 0,
         solrConfigOverridenullfalsegetExtraServlets(), getExtraRequestFilters());
     jetty.setShards(shardList);
     jetty.setDataDir(getDataDir(dataDir));
     jetty.start();
     
     return jetty;
   }
   
   public JettySolrRunner createJetty(File solrHomeString dataDirString shardListString solrConfigOverrideString schemaOverridethrows Exception {
     // randomly test a relative solr.home path
     if (random().nextBoolean()) {
       solrHome = getRelativeSolrHomePath(solrHome);
     }
     
     JettySolrRunner jetty = new JettySolrRunner(solrHome.getPath(), , 0, solrConfigOverrideschemaOverridefalsegetExtraServlets(), getExtraRequestFilters());
     jetty.setShards(shardList);
     jetty.setDataDir(getDataDir(dataDir));
     jetty.start();
     
     return jetty;
   }

  
Creates a JettySolrRunner with a socket proxy sitting infront of the Jetty server, which gives us the ability to simulate network partitions without having to fuss with IPTables.
 
   public JettySolrRunner createProxiedJetty(File solrHomeString dataDir,
                                             String shardListString solrConfigOverrideString schemaOverride)
       throws Exception {
 
     JettySolrRunner jetty = new JettySolrRunner(solrHome.getPath(), ,
         0, solrConfigOverrideschemaOverridefalse,
     jetty.setShards(shardList);
     jetty.setDataDir(getDataDir(dataDir));
 
     // setup to proxy Http requests to this server unless it is the control
     // server
     int proxyPort = getNextAvailablePort();
     jetty.setProxyPort(proxyPort);
     jetty.start();
 
     // create a socket proxy for the jetty server ...
     SocketProxy proxy = new SocketProxy(proxyPortjetty.getBaseUrl().toURI());
     .put(proxy.getUrl(), proxy);
 
     return jetty;
   }
 
   protected int getReplicaPort(Replica replica) {
     String replicaNode = replica.getNodeName();
     String tmp = replicaNode.substring(replicaNode.indexOf(':')+1);
     if (tmp.indexOf('_') != -1)
       tmp = tmp.substring(0,tmp.indexOf('_'));
     return Integer.parseInt(tmp);
   }
 
   protected JettySolrRunner getJettyOnPort(int port) {
     JettySolrRunner theJetty = null;
     for (JettySolrRunner jetty : ) {
       if (port == jetty.getLocalPort()) {
         theJetty = jetty;
         break;
       }
     }
 
     if (theJetty == null) {
       if (.getLocalPort() == port) {
         theJetty = ;
       }
     }
 
     if (theJetty == null)
       fail("Not able to find JettySolrRunner for port: "+port);
 
     return theJetty;
   }
 
   protected SocketProxy getProxyForReplica(Replica replicathrows Exception {
     String replicaBaseUrl = replica.getStr(.);
     assertNotNull(replicaBaseUrl);
     URL baseUrl = new URL(replicaBaseUrl);
 
     SocketProxy proxy = .get(baseUrl.toURI());
     if (proxy == null && !baseUrl.toExternalForm().endsWith("/")) {
       baseUrl = new URL(baseUrl.toExternalForm() + "/");
       proxy = .get(baseUrl.toURI());
     }
     assertNotNull("No proxy found for " + baseUrl + "!"proxy);
     return proxy;
   }
 
   protected int getNextAvailablePort() throws Exception {
     int port = -1;
     try (ServerSocket s = new ServerSocket(0)) {
       port = s.getLocalPort();
     }
     return port;
   }
 
   private File getRelativeSolrHomePath(File solrHome) {
     String path = SolrResourceLoader.normalizeDir(new File(".").getAbsolutePath());
     String base = new File(solrHome.getPath()).getAbsolutePath();
     
     if (base.startsWith(".")) {
       base = base.replaceFirst("\\."new File(".").getName());
     }
 
     if (path.endsWith(. + ".")) {
       path = path.substring(0, path.length() - 2);
     }
     
     int splits = path.split("\\" + .).length;
     
     StringBuilder p = new StringBuilder();
     for (int i = 0; i < splits - 2; i++) {
       p.append("..").append(.);
     }   
     
     String prefix = FilenameUtils.getPrefix(path);
     if (base.startsWith(prefix)) {
       base = base.substring(prefix.length());
     }
 
     solrHome = new File(p.toString() + base);
     return solrHome;
   }
   
   protected void updateMappingsFromZk(List<JettySolrRunnerjettysList<SolrServerclientsthrows Exception {
     updateMappingsFromZk(jettysclientsfalse);
   }
   
   protected void updateMappingsFromZk(List<JettySolrRunnerjettysList<SolrServerclientsboolean allowOverShardingthrows Exception {
     ZkStateReader zkStateReader = .getZkStateReader();
     zkStateReader.updateClusterState(true);
     .clear();
     .clear();
     
     ClusterState clusterState = zkStateReader.getClusterState();
     DocCollection coll = clusterState.getCollection();
 
     List<CloudSolrServerClienttheClients = new ArrayList<>();
     for (SolrServer client : clients) {
       // find info for this client in zk 
       nextClient:
       // we find out state by simply matching ports...
       for (Slice slice : coll.getSlices()) {
         for (Replica replica : slice.getReplicas()) {
           int port = new URI(((HttpSolrServerclient).getBaseURL())
               .getPort();
           
           if (replica.getStr(.).contains(":" + port)) {
             CloudSolrServerClient csc = new CloudSolrServerClient();
             csc.solrClient = client;
             csc.port = port;
             csc.shardName = replica.getStr(.);
             csc.info = replica;
             
             theClients .add(csc);
             
             break nextClient;
           }
         }
       }
     }
  
     for (JettySolrRunner jetty : jettys) {
       int port = jetty.getLocalPort();
       if (port == -1) {
         throw new RuntimeException("Cannot find the port for jetty");
       }
       
       nextJetty:
       for (Slice slice : coll.getSlices()) {
         Set<Entry<String,Replica>> entries = slice.getReplicasMap().entrySet();
         for (Entry<String,Replicaentry : entries) {
           Replica replica = entry.getValue();
           if (replica.getStr(.).contains(":" + port)) {
             List<CloudJettyRunnerlist = .get(slice.getName());
             if (list == null) {
               list = new ArrayList<>();
               .put(slice.getName(), list);
             }
             boolean isLeader = slice.getLeader() == replica;
             CloudJettyRunner cjr = new CloudJettyRunner();
             cjr.jetty = jetty;
             cjr.info = replica;
             cjr.nodeName = replica.getStr(.);
             cjr.coreNodeName = entry.getKey();
             cjr.url = replica.getStr(.) + "/" + replica.getStr(.);
             cjr.client = findClientByPort(porttheClients);
             list.add(cjr);
             if (isLeader) {
               .put(slice.getName(), cjr);
             }
             .add(cjr);
             break nextJetty;
           }
         }
       }
     }
     
     // # of jetties may not match replicas in shard here, because we don't map
     // jetties that are not running - every shard should have at least one
     // running jetty though
     for (Slice slice : coll.getSlices()) {
       // check that things look right
       List<CloudJettyRunnerjetties = .get(slice.getName());
       if (!allowOverSharding) {
         assertNotNull("Test setup problem: We found no jetties for shard: "
             + slice.getName() + " just:" + .keySet(), jetties);
         
         assertEquals("slice:" + slice.getName(), slice.getReplicas().size(),
             jetties.size());
       }
     }
   }
   
   private CloudSolrServerClient findClientByPort(int portList<CloudSolrServerClienttheClients) {
     for (CloudSolrServerClient client : theClients) {
       if (client.port == port) {
         return client;
       }
     }
     throw new IllegalArgumentException("Client with the given port does not exist:" + port);
   }
 
   protected void setDistributedParams(ModifiableSolrParams params) {
     
     if (.nextBoolean()) {
       // don't set shards, let that be figured out from the cloud state
     } else {
       // use shard ids rather than physical locations
       StringBuilder sb = new StringBuilder();
       for (int i = 0; i < i++) {
         if (i > 0) sb.append(',');
         sb.append("shard" + (i + 1));
       }
       params.set("shards"sb.toString());
     }
   }
   
   protected void indexDoc(SolrInputDocument docthrows IOException,
       SolrServerException {
     
     UpdateRequest req = new UpdateRequest();
     req.add(doc);
     req.setParam("CONTROL""TRUE");
     req.process();
     
     // if we wanted to randomly pick a client - but sometimes they may be
     // down...
     
     // boolean pick = random.nextBoolean();
     //
     // int which = (doc.getField(id).toString().hashCode() & 0x7fffffff) %
     // sliceCount;
     //
     // if (pick && sliceCount > 1) {
     // which = which + ((shardCount / sliceCount) *
     // random.nextInt(sliceCount-1));
     // }
     //
     // HttpSolrServer client = (HttpSolrServer)
     // clients.get(which);
     
     UpdateRequest ureq = new UpdateRequest();
     ureq.add(doc);
     // ureq.setParam(UpdateParams.UPDATE_CHAIN, DISTRIB_UPDATE_CHAIN);
     ureq.process();
   }
   
   protected void index_specific(int serverNumberObject... fields)
       throws Exception {
     SolrInputDocument doc = new SolrInputDocument();
     for (int i = 0; i < fields.lengthi += 2) {
       doc.addField((String) (fields[i]), fields[i + 1]);
     }
     .add(doc);
     
     HttpSolrServer client = (HttpSolrServer
         .get(serverNumber);
     
     UpdateRequest ureq = new UpdateRequest();
     ureq.add(doc);
     // ureq.setParam("update.chain", DISTRIB_UPDATE_CHAIN);
     ureq.process(client);
   }
   
   protected void index_specific(SolrServer clientObject... fields)
       throws Exception {
     SolrInputDocument doc = new SolrInputDocument();
     for (int i = 0; i < fields.lengthi += 2) {
       doc.addField((String) (fields[i]), fields[i + 1]);
     }
     
     UpdateRequest ureq = new UpdateRequest();
     ureq.add(doc);
     // ureq.setParam("update.chain", DISTRIB_UPDATE_CHAIN);
     ureq.process(client);
     
     // add to control second in case adding to shards fails
     .add(doc);
   }
   
   protected void del(String qthrows Exception {
     .deleteByQuery(q);

    
for (SolrServer client : clients) { UpdateRequest ureq = new UpdateRequest(); // ureq.setParam("update.chain", DISTRIB_UPDATE_CHAIN); ureq.deleteByQuery(q).process(client); }
 
   }// serial commit...
   
   protected void waitForRecoveriesToFinish(boolean verbose)
       throws Exception {
     ZkStateReader zkStateReader = .getZkStateReader();
     super.waitForRecoveriesToFinish(zkStateReaderverbose);
   }
   
   protected void waitForRecoveriesToFinish(String collectionboolean verbose)
       throws Exception {
     ZkStateReader zkStateReader = .getZkStateReader();
     super.waitForRecoveriesToFinish(collectionzkStateReaderverbose);
   }
   
   protected void waitForRecoveriesToFinish(boolean verboseint timeoutSeconds)
       throws Exception {
     ZkStateReader zkStateReader = .getZkStateReader();
     super.waitForRecoveriesToFinish(zkStateReaderverbosetruetimeoutSeconds);
   }
   
   protected void checkQueries() throws Exception {
 
     .put("_version_");
 
     query("q""*:*""sort""n_tl1 desc");
 
     .put("response");  // get?ids=a,b,c requests are unordered
     String ids = "987654";
     for (int i=0; i<20; i++) {
       query("qt","/get""id",Integer.toString(i));
       query("qt","/get""ids",Integer.toString(i));
       ids = ids + ',' + Integer.toString(i);
       query("qt","/get""ids",ids);
     }
     .remove("response");
 
 
 
     // random value sort
     for (String f : ) {
       query("q""*:*""sort"f + " desc");
       query("q""*:*""sort"f + " asc");
     }
     
     // these queries should be exactly ordered and scores should exactly match
     query("q""*:*""sort" + " desc");
     query("q""*:*""sort" + " asc");
     query("q""*:*""sort" + " desc""fl""*,score");
     query("q""*:*""sort""n_tl1 asc""fl""score"); // test legacy
                                                            // behavior -
                                                            // "score"=="*,score"
     query("q""*:*""sort""n_tl1 desc");
     .put("maxScore");
     query("q""{!func}" + );// does not expect maxScore. So if it comes
                                // ,ignore it.
                                // JavaBinCodec.writeSolrDocumentList()
     // is agnostic of request params.
     .remove("maxScore");
     query("q""{!func}" + "fl""*,score"); // even scores should match
                                                  // exactly here
     
     .put("highlighting");
     .put("response");
     
     .put("maxScore");
     query("q""quick");
     query("q""all""fl""id""start""0");
     query("q""all""fl""foofoofoo""start""0"); // no fields in returned
                                                         // docs
     query("q""all""fl""id""start""100");
     
     .put("score");
     query("q""quick""fl""*,score");
     query("q""all""fl""*,score""start""1");
     query("q""all""fl""*,score""start""100");
     
     query("q""now their fox sat had put""fl""*,score""hl""true",
         "hl.fl");
     
     query("q""now their fox sat had put""fl""foofoofoo""hl""true",
         "hl.fl");
     
     query("q""matchesnothing""fl""*,score");
     
     query("q""*:*""rows", 100, "facet""true""facet.field");
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.limit", -1, "facet.sort""count");
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.limit", -1, "facet.sort""count""facet.mincount", 2);
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.limit", -1, "facet.sort""index");
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.limit", -1, "facet.sort""index""facet.mincount", 2);
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.limit", 1);
     query("q""*:*""rows", 100, "facet""true""facet.query""quick",
         "facet.query""all""facet.query""*:*");
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.offset", 1);
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.mincount", 2);
     
     // test faceting multiple things at once
     query("q""*:*""rows", 100, "facet""true""facet.query""quick",
         "facet.query""all""facet.query""*:*""facet.field");
     
     // test filter tagging, facet exclusion, and naming (multi-select facet
     // support)
     query("q""*:*""rows", 100, "facet""true""facet.query",
         "{!key=myquick}quick""facet.query""{!key=myall ex=a}all",
         "facet.query""*:*""facet.field""{!key=mykey ex=a}" + ,
         "facet.field""{!key=other ex=b}" + "facet.field",
         "{!key=again ex=a,b}" + "facet.field""fq",
         "{!tag=a}id:[1 TO 7]""fq""{!tag=b}id:[3 TO 9]");
     query("q""*:*""facet""true""facet.field",
         "{!ex=t1}SubjectTerms_mfacet""fq",
         "{!tag=t1}SubjectTerms_mfacet:(test 1)""facet.limit""10",
         "facet.mincount""1");
     
     // test field that is valid in schema but missing in all shards
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.mincount", 2);
     // test field that is valid in schema and missing in some shards
     query("q""*:*""rows", 100, "facet""true""facet.field",
         "facet.mincount", 2);
     
     query("q""*:*""sort" + " desc""stats""true""stats.field");
     
     // Try to get better coverage for refinement queries by turning off over
     // requesting.
     // This makes it much more likely that we may not get the top facet values
     // and hence
     // we turn of that checking.
     .put("facet_fields");
     query("q""*:*""rows", 0, "facet""true""facet.field",
         "facet.limit", 5, "facet.shard.limit", 5);
     // check a complex key name
     query("q""*:*""rows", 0, "facet""true""facet.field",
         "{!key='a b/c \\' \\} foo'}" + "facet.limit", 5,
         "facet.shard.limit", 5);
     .remove("facet_fields");
     
     query("q""*:*""sort""n_tl1 desc");
     
     // index the same document to two shards and make sure things
     // don't blow up.
     // assumes first n clients are first n shards
     if (.size() >= 2) {
       index(, 100, , 107, "oh no, a duplicate!");
       for (int i = 0; i < i++) {
         index_specific(i, 100, , 107, "oh no, a duplicate!");
       }
       commit();
       query("q""duplicate""hl""true""hl.fl");
       query("q""fox duplicate horses""hl""true""hl.fl");
       query("q""*:*""rows", 100);
     }
   }
   
   protected void indexAbunchOfDocs() throws Exception {
     indexr(, 2, , 50, "to come to the aid of their country.");
     indexr(, 3, ,  2, "how now brown cow");
     indexr(, 4, , -100, ,
         "the quick fox jumped over the lazy dog");
     indexr(, 5, , 500, ,
         "the quick fox jumped way over the lazy dog");
     indexr(, 6, , -600, "humpty dumpy sat on a wall");
     indexr(, 7, , 123, "humpty dumpy had a great fall");
     indexr(, 8, , 876, ,
         "all the kings horses and all the kings men");
     indexr(, 9, , 7, "couldn't put humpty together again");
     indexr(, 10, , 4321, "this too shall pass");
     indexr(, 11, , -987, ,
         "An eye for eye only ends up making the whole world blind.");
     indexr(, 12, , 379, ,
         "Great works are performed, not by strength, but by perseverance.");
     indexr(, 13, , 232, "no eggs on wall, lesson learned",
         "odd man out");
     
     indexr(, 14, "SubjectTerms_mfacet"new String[] {"mathematical models",
         "mathematical analysis"});
     indexr(, 15, "SubjectTerms_mfacet"new String[] {"test 1""test 2",
         "test3"});
     indexr(, 16, "SubjectTerms_mfacet"new String[] {"test 1""test 2",
         "test3"});
     String[] vals = new String[100];