Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * 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.junit.Rule;
  import org.slf4j.Logger;
  
  import java.io.File;
  import java.io.Reader;
  import java.net.URL;
  import java.util.Arrays;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.HashSet;
 import java.util.Map;
 
 import static com.google.common.base.Preconditions.checkNotNull;

A junit4 Solr test harness that extends LuceneTestCaseJ4. To change which core is used when loading the schema and solrconfig.xml, simply invoke the initCore(String, String, String, String) method. Unlike AbstractSolrTestCase, a new core is not created for each test method.
 
 @ThreadLeakFilters(defaultFilters = true, filters = {
 })
 @SuppressSysoutChecks(bugUrl = "Solr dumps tons of logs to console.")
 public abstract class SolrTestCaseJ4 extends LuceneTestCase {
   public static int DEFAULT_CONNECTION_TIMEOUT = 60000;  // default socket connection timeout in ms
 
  
Annotation for test classes that want to disable SSL
 
   public @interface SuppressSSL {
    
Point to JIRA entry.
 
     public String bugUrl() default "None";
   }
   
   // 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;
 
   public static TestRule solrClassRules = 
     RuleChain.outerRule(new SystemPropertiesRestoreRule())
              .around(new RevertDefaultThreadHandlerRule());
 
   @Rule
   public TestRule solrTestRules = 
     RuleChain.outerRule(new SystemPropertiesRestoreRule());
 
   @SuppressWarnings("unused")
   private static void beforeClass() {
      = createTempDir("init-core-data");
 
     ..println("Creating dataDir: " + .getAbsolutePath());
 
     System.setProperty("zookeeper.forceSync""no");
     System.setProperty("jetty.testMode""true");
     System.setProperty("enable.update.log"usually() ? "true" : "false");
     System.setProperty("tests.shardhandler.randomSeed", Long.toString(random().nextLong()));
     System.setProperty("solr.clustering.enabled""false");
     setupLogging();
     ignoreException("ignore_exception");
     newRandomConfig();
     
      = buildSSLConfig();
     //will use ssl specific or default depending on sslConfig
     if(isSSLMode()) {
       // SolrCloud tests should usually clear this
       System.setProperty("urlScheme""https");
     }
   }
 
   @SuppressWarnings("unused")
   private static void afterClass() throws Exception {
     try {
       deleteCore();
       resetExceptionIgnores();
       endTrackingSearchers();
       endTrackingZkClients();
       resetFactory();
     } finally {
        = null;
       System.clearProperty("zookeeper.forceSync");
       System.clearProperty("jetty.testMode");
       System.clearProperty("tests.shardhandler.randomSeed");
       System.clearProperty("enable.update.log");
       System.clearProperty("useCompoundFile");
       System.clearProperty("urlScheme");
       
       if (isSSLMode()) {
         HttpClientUtil.setConfigurer(new HttpClientConfigurer());
       }
 
       // clean up static
        = null;
     }
     
     IpTables.unblockAllPorts();
   }
   
   protected static boolean isSSLMode() {
     return  != null && .isSSLMode();
   }
 
   private static boolean changedFactory = false;
   private static String savedFactory;
  
Use a different directory factory. Passing "null" sets to an FS-based factory
 
   public static void useFactory(String factorythrows Exception {
     // allow calling more than once so a subclass can override a base class
     if (!) {
        = System.getProperty("solr.DirectoryFactory");
     }
 
     if (factory == null) {
       factory = random().nextInt(100) < 75 ? "solr.NRTCachingDirectoryFactory" : "solr.StandardDirectoryFactory"// test the default most of the time
     }
     System.setProperty("solr.directoryFactory"factory);
      = true;
   }
 
   public static void resetFactory() throws Exception {
     if (!return;
      = false;
     if ( != null) {
       System.setProperty("solr.directoryFactory");
     } else {
       System.clearProperty("solr.directoryFactory");
     }
   }
 
   private static SSLTestConfig buildSSLConfig() {
     // test has been disabled
     if (RandomizedContext.current().getTargetClass().isAnnotationPresent(SuppressSSL.class)) {
       return new SSLTestConfig();
     }
     
     final boolean trySsl = random().nextBoolean();
     boolean trySslClientAuth = random().nextBoolean();
     if (.) {
       trySslClientAuth = false;
     }
     
     .info("Randomized ssl ({}) and clientAuth ({})"trySsl,
         trySslClientAuth);
     
     return new SSLTestConfig(trySsltrySslClientAuth);
   }
   
   protected static String buildUrl(final int portfinal String context) {
     return (isSSLMode() ? "https" : "http") + "://127.0.0.1:" + port + context;
   }

  
Call this from

Parameters:
solrHome The solr home directory.
xmlStr - the text of an XML file to use. If null, use the what's the absolute minimal file.
Throws:
java.lang.Exception Lost of file-type things can go wrong.
BeforeClass:
to set up the test harness and update handler with no cores.
 
   public static void setupNoCoreTest(File solrHomeString xmlStrthrows Exception {
 
     File tmpFile = new File(solrHome.);
     if (xmlStr == null) {
       xmlStr = "<solr></solr>";
     }
     FileUtils.write(tmpFilexmlStr.);
 
     SolrResourceLoader loader = new SolrResourceLoader(solrHome.getAbsolutePath());
      = new TestHarness(loader, ConfigSolr.fromFile(loadernew File(solrHome"solr.xml")));
      = .getRequestFactory("standard", 0, 20, ."2.2");
   }
  
  
sets system properties based on org.apache.lucene.util.LuceneTestCase.newIndexWriterConfig(org.apache.lucene.analysis.Analyzer) configs can use these system properties to vary the indexwriter settings
 
   public static void newRandomConfig() {
 
     System.setProperty("useCompoundFile", String.valueOf(iwc.getUseCompoundFile()));
 
     System.setProperty("solr.tests.maxBufferedDocs", String.valueOf(iwc.getMaxBufferedDocs()));
     System.setProperty("solr.tests.ramBufferSizeMB", String.valueOf(iwc.getRAMBufferSizeMB()));
     System.setProperty("solr.tests.mergeScheduler"iwc.getMergeScheduler().getClass().getName());
 
     // don't ask iwc.getMaxThreadStates(), sometimes newIWC uses 
     // RandomDocumentsWriterPerThreadPool and all hell breaks loose
     int maxIndexingThreads = rarely(random())
       ? TestUtil.nextInt(random(), 5, 20) // crazy value
       : TestUtil.nextInt(random(), 1, 4); // reasonable value
     System.setProperty("solr.tests.maxIndexingThreads", String.valueOf(maxIndexingThreads));
   }
 
   public static Throwable getWrappedException(Throwable e) {
     while (e != null && e.getCause() != e && e.getCause() != null) {
       e = e.getCause();
     }
     return e;
   }
 
   public void setUp() throws Exception {
     super.setUp();
     .info("###Starting " + getTestName());  // returns <unknown>???
   }
 
   public void tearDown() throws Exception {
     .info("###Ending " + getTestName());    
     super.tearDown();
   }
 
   public static SolrLogFormatter formatter;
 
   public static void setupLogging() {
     boolean register = false;
     Handler[] handlers = java.util.logging.Logger.getLogger("").getHandlers();
     ConsoleHandler consoleHandler = null;
     for (Handler handler : handlers) {
       if (handler instanceof ConsoleHandler) {
         consoleHandler = (ConsoleHandler)handler;
         break;
       }
     }
 
     if (consoleHandler == null) {
       consoleHandler = new ConsoleHandler();
       register = true;
     }
 
     consoleHandler.setLevel(.);
      = new SolrLogFormatter();
     consoleHandler.setFormatter();
 
     if (register) {
       java.util.logging.Logger.getLogger("").addHandler(consoleHandler);
     }
   }
 
   public static void setLoggingLevel(Level level) {
     java.util.logging.Logger logger = java.util.logging.Logger.getLogger("");
     logger.setLevel(level);
   }


  
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 configString schemathrows Exception {
     initCore(configschemaTEST_HOME());
   }

  
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 configString schemaString solrHomethrows Exception {
     assertNotNull(solrHome);
      = config;
      = schema;
      = solrHome;
     if (solrHome != null) {
       System.setProperty("solr.solr.home"solrHome);
     }
     initCore();
   }

  
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 configString schemaString solrHomeString pCoreNamethrows Exception {
     =pCoreName;
     initCore(config,schema,solrHome);
   }
   
   static long numOpens;
   static long numCloses;
   public static void startTrackingSearchers() {
     if ( != 0 ||  != 0) {
       // NOTE: some other tests don't use this base class and hence won't reset the counts.
       .warn("startTrackingSearchers: numOpens="++" numCloses="+);
        =  = 0;
     }
   }
   static long zkClientNumOpens;
   static long zkClientNumCloses;
   public static void startTrackingZkClients() {
   }
 
   public static void endTrackingSearchers() {
      long endNumOpens = ..get();
      long endNumCloses = ..get();
 
      // wait a bit in case any ending threads have anything to release
      int retries = 0;
      while (endNumOpens -  != endNumCloses - ) {
        if (retries++ > 120) {
          break;
        }
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {}
        endNumOpens = ..get();
        endNumCloses = ..get();
      }
 
 
      if (endNumOpens- != endNumCloses-) {
        String msg = "ERROR: SolrIndexSearcher opens=" + (endNumOpens-) + " closes=" + (endNumCloses-);
        .error(msg);
        // if its TestReplicationHandler, ignore it. the test is broken and gets no love
        if ("TestReplicationHandler".equals(RandomizedContext.current().getTargetClass().getSimpleName())) {
          .warn("TestReplicationHandler wants to fail!: " + msg);
        } else {
          fail(msg);
        }
      }
   }
   
   public static void endTrackingZkClients() {
     long endNumOpens = ..get();
     long endNumCloses = ..get();
 
 
     if (endNumOpens- != endNumCloses-) {
       String msg = "ERROR: SolrZkClient opens=" + (endNumOpens-) + " closes=" + (endNumCloses-);
       .error(msg);
       fail(msg);
     }
  }
  
  
Causes an exception matching the regex pattern to not be logged.
 
   public static void ignoreException(String pattern) {
     if (. == null)
       . = new HashSet<>();
     ..add(pattern);
   }
 
   public static void unIgnoreException(String pattern) {
     if (. != null)
       ..remove(pattern);
   }
 
   public static void resetExceptionIgnores() {
     . = null;
     ignoreException("ignore_exception");  // always ignore "ignore_exception"    
   }
 
   protected static String getClassName() {
     return getTestClass().getName();
   }
 
   protected static String getSimpleClassName() {
     return getTestClass().getSimpleName();
   }
 
   protected static String configString;
   protected static String schemaString;
   protected static String testSolrHome;
 
   protected static SolrConfig solrConfig;

  
Harness initialized by initTestHarness.

For use in test methods as needed.

 
   protected static TestHarness h;

  
LocalRequestFactory initialized by initTestHarness using sensible defaults.

For use in test methods as needed.

 
   protected static TestHarness.LocalRequestFactory lrf;


  
Subclasses must define this method to return the name of the schema.xml they wish to use.
 
   public static String getSchemaFile() {
     return ;
   }

  
Subclasses must define this method to return the name of the solrconfig.xml they wish to use.
 
   public static String getSolrConfigFile() {
     return ;
   }

  
The directory used to story the index managed by the TestHarness
 
   protected static volatile File initCoreDataDir;
   
   // hack due to File dataDir
   protected static String hdfsDataDir;

  
Initializes things your test might need
  • Creates a dataDir in the "java.io.tmpdir"
  • initializes the TestHarness h using this data directory, and getSchemaPath()
  • initializes the LocalRequestFactory lrf using sensible defaults.
 
 
   public static Logger log = LoggerFactory.getLogger(SolrTestCaseJ4.class);
 
   private static String factoryProp;
 
 
   public static void initCore() throws Exception {
     .info("####initCore");
 
     ignoreException("ignore_exception");
      = System.getProperty("solr.directoryFactory");
     if ( == null) {
       System.setProperty("solr.directoryFactory","solr.RAMDirectoryFactory");
     }
 
     // other  methods like starting a jetty instance need these too
     System.setProperty("solr.test.sys.prop1""propone");
     System.setProperty("solr.test.sys.prop2""proptwo");
 
     String configFile = getSolrConfigFile();
     if (configFile != null) {
       createCore();
     }
     .info("####initCore end");
   }
 
   public static void createCore() {
      = new TestHarness == null ? .getAbsolutePath() : ,
             ,
             getSchemaFile());
      = .getRequestFactory
             ("standard",0,20,.,"2.2");
   }
 
   public static CoreContainer createCoreContainer(String solrHomeString solrXML) {
      = checkNotNull(solrHome);
      = new TestHarness(solrHomesolrXML);
      = .getRequestFactory("standard", 0, 20, ."2.2");
     return .getCoreContainer();
   }
 
   public static CoreContainer createDefaultCoreContainer(String solrHome) {
      = checkNotNull(solrHome);
      = new TestHarness("collection1".getAbsolutePath(), "solrconfig.xml""schema.xml");
      = .getRequestFactory("standard", 0, 20, ."2.2");
     return .getCoreContainer();
   }
 
   public static boolean hasInitException(String message) {
       if (entry.getValue()..getMessage().contains(message))
         return true;
     }
     return false;
   }
 
   public static boolean hasInitException(Class<? extends ExceptionexceptionType) {
       if (exceptionType.isAssignableFrom(entry.getValue()..getClass()))
         return true;
     }
     return false;
   }

  
Subclasses that override setUp can optionally call this method to log the fact that their setUp process has ended.
 
   public void postSetUp() {
     .info("####POSTSETUP " + getTestName());
   }


  
Subclasses that override tearDown can optionally call this method to log the fact that the tearDown process has started. This is necessary since subclasses will want to call super.tearDown() at the *end* of their tearDown method.
 
   public void preTearDown() {
     .info("####PRETEARDOWN " + getTestName());
   }

  
Shuts down the test harness, and makes the best attempt possible to delete dataDir, unless the system property "solr.test.leavedatadir" is set.
 
   public static void deleteCore() {
     .info("###deleteCore" );
     if ( != null) { .close(); }
 
     if ( == null) {
       System.clearProperty("solr.directoryFactory");
     }
     
      = null;
      = null;
      = null;
      =  = null;
   }


  
Validates an update XML String is successful
 
   public static void assertU(String update) {
     assertU(nullupdate);
   }

  
Validates an update XML String is successful
 
   public static void assertU(String messageString update) {
     checkUpdateU(messageupdatetrue);
   }

  
Validates an update XML String failed
 
   public static void assertFailedU(String update) {
     assertFailedU(nullupdate);
   }

  
Validates an update XML String failed
 
   public static void assertFailedU(String messageString update) {
     checkUpdateU(messageupdatefalse);
   }

  
Checks the success or failure of an update message
 
   private static void checkUpdateU(String messageString updateboolean shouldSucceed) {
     try {
       String m = (null == message) ? "" : message + " ";
       if (shouldSucceed) {
            String res = .validateUpdate(update);
          if (res != nullfail(m + "update was not successful: " + res);
       } else {
            String res = .validateErrorUpdate(update);
          if (res != nullfail(m + "update succeeded, but should have failed: " + res);
       }
     } catch (SAXException e) {
       throw new RuntimeException("Invalid XML"e);
     }
   }

  
Validates a query matches some XPath test expressions and closes the query
 
   public static void assertQ(SolrQueryRequest reqString... tests) {
     assertQ(nullreqtests);
   }

  
Validates a query matches some XPath test expressions and closes the query
 
   public static void assertQ(String messageSolrQueryRequest reqString... tests) {
     try {
       String m = (null == message) ? "" : message + " ";
       String response = .query(req);
 
       if (req.getParams().getBool("facet"false)) {
         // add a test to ensure that faceting did not throw an exception
         // internally, where it would be added to facet_counts/exception
         String[] allTests = new String[tests.length+1];
         System.arraycopy(tests,0,allTests,1,tests.length);
         allTests[0] = "*[count(//lst[@name='facet_counts']/*[@name='exception'])=0]";
         tests = allTests;
       }
 
       String results = .validateXPath(responsetests);
 
       if (null != results) {
         String msg = "REQUEST FAILED: xpath=" + results
             + "\n\txml response was: " + response
             + "\n\trequest was:" + req.getParamString();
 
         .error(msg);
         throw new RuntimeException(msg);
       }
 
     } catch (XPathExpressionException e1) {
       throw new RuntimeException("XPath is invalid"e1);
     } catch (Exception e2) {
       SolrException.log(,"REQUEST FAILED: " + req.getParamString(), e2);
       throw new RuntimeException("Exception during query"e2);
     }
   }

  
Makes a query request and returns the JSON string response
 
   public static String JQ(SolrQueryRequest reqthrows Exception {
     SolrParams params = req.getParams();
     if (!"json".equals(params.get("wt","xml")) || params.get("indent")==null) {
       ModifiableSolrParams newParams = new ModifiableSolrParams(params);
       newParams.set("wt","json");
       if (params.get("indent")==nullnewParams.set("indent","true");
       req.setParams(newParams);
     }
 
     String response;
     boolean failed=true;
     try {
       response = .query(req);
       failed = false;
     } finally {
       if (failed) {
         .error("REQUEST FAILED: " + req.getParamString());
       }
     }
 
     return response;
   }

  
Validates a query matches some JSON test expressions using the default double delta tolerance.

Returns:
The request response as a JSON String if all test patterns pass
See also:
JSONTestUtil.DEFAULT_DELTA
assertJQ(org.apache.solr.request.SolrQueryRequest,double,java.lang.String[])
 
   public static String assertJQ(SolrQueryRequest reqString... teststhrows Exception {
     return assertJQ(req.tests);
   }
  
Validates a query matches some JSON test expressions and closes the query. The text expression is of the form path:JSON. To facilitate easy embedding in Java strings, the JSON tests can have double quotes replaced with single quotes.

Please use this with care: this makes it easy to match complete structures, but doing so can result in fragile tests if you are matching more than what you want to test.

Parameters:
req Solr request to execute
delta tolerance allowed in comparing float/double values
tests JSON path expression + '==' + expected value
Returns:
The request response as a JSON String if all test patterns pass
 
   public static String assertJQ(SolrQueryRequest reqdouble deltaString... teststhrows Exception {
     SolrParams params =  null;
     try {
       params = req.getParams();
       if (!"json".equals(params.get("wt","xml")) || params.get("indent")==null) {
         ModifiableSolrParams newParams = new ModifiableSolrParams(params);
         newParams.set("wt","json");
         if (params.get("indent")==nullnewParams.set("indent","true");
         req.setParams(newParams);
       }
 
       String response;
       boolean failed=true;
       try {
         response = .query(req);
         failed = false;
       } finally {
         if (failed) {
           .error("REQUEST FAILED: " + req.getParamString());
         }
       }
 
       for (String test : tests) {
         if (test == null || test.length()==0) continue;
         String testJSON = json(test);
 
         try {
           failed = true;
           String err = JSONTestUtil.match(responsetestJSONdelta);
           failed = false;
           if (err != null) {
             .error("query failed JSON validation. error=" + err +
                 "\n expected =" + testJSON +
                 "\n response = " + response +
                 "\n request = " + req.getParamString()
             );
             throw new RuntimeException(err);
           }
         } finally {
           if (failed) {
             .error("JSON query validation threw an exception." + 
                 "\n expected =" + testJSON +
                 "\n response = " + response +
                 "\n request = " + req.getParamString()
             );
           }
         }
       }
       return response;
     } finally {
       // restore the params
       if (params != null && params != req.getParams()) req.setParams(params);
     }
   }  


  
Makes sure a query throws a SolrException with the listed response code
 
   public static void assertQEx(String messageSolrQueryRequest reqint code ) {
     try {
       ignoreException(".");
       .query(req);
       failmessage );
     } catch (SolrException sex) {
       assertEqualscodesex.code() );
     } catch (Exception e2) {
       throw new RuntimeException("Exception during query"e2);
     } finally {
       unIgnoreException(".");
     }
   }
 
   public static void assertQEx(String messageSolrQueryRequest reqSolrException.ErrorCode code ) {
     try {
       ignoreException(".");
       .query(req);
       failmessage );
     } catch (SolrException e) {
       assertEqualscode.codee.code() );
     } catch (Exception e2) {
       throw new RuntimeException("Exception during query"e2);
     } finally {
       unIgnoreException(".");
     }
   }
  
Makes sure a query throws a SolrException with the listed response code and expected message

Parameters:
failMessage The assert message to show when the query doesn't throw the expected exception
exceptionMessage A substring of the message expected in the exception
req Solr request
code expected error code for the query
 
   public static void assertQEx(String failMessageString exceptionMessageSolrQueryRequest reqSolrException.ErrorCode code ) {
     try {
       ignoreException(".");
       .query(req);
       failfailMessage );
     } catch (SolrException e) {
       assertEqualscode.codee.code() );
       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);
     } finally {
       unIgnoreException(".");
     }
   }


  
 
   public static String optimize(String... args) {
     return TestHarness.optimize(args);
   }
  
 
   public static String commit(String... args) {
     return TestHarness.commit(args);
   }

  
Generates a simple <add><doc>... XML String with no options

Parameters:
fieldsAndValues 0th and Even numbered args are fields names odds are field values.
See also:
add(org.apache.solr.SolrTestCaseJ4.XmlDoc,java.lang.String[])
doc(java.lang.String[])
 
   public static String adoc(String... fieldsAndValues) {
     XmlDoc d = doc(fieldsAndValues);
     return add(d);
   }

  
Generates a simple <add><doc>... XML String with no options
 
   public static String adoc(SolrInputDocument sdoc) {
     StringWriter out = new StringWriter(512);
     try {
       out.append("<add>");
       ClientUtils.writeXML(sdocout);
       out.append("</add>");
     } catch (IOException e) {
       throw new RuntimeException("Inexplicable IO error from StringWriter"e);
     }
     return out.toString();
   }


  
Generates an <add><doc>... XML String with options on the add.

Parameters:
doc the Document to add
args 0th and Even numbered args are param names, Odds are param values.
See also:
add(org.apache.solr.SolrTestCaseJ4.XmlDoc,java.lang.String[])
doc(java.lang.String[])
 
   public static String add(XmlDoc docString... args) {
     try {
       StringWriter r = new StringWriter();
 
       // this is annoying
       if (null == args || 0 == args.length) {
         r.write("<add>");
         r.write(doc.xml);
         r.write("</add>");
       } else {
         XML.writeUnescapedXML(r"add"doc.xml, (Object[])args);
       }
 
       return r.getBuffer().toString();
     } catch (IOException e) {
       throw new RuntimeException
         ("this should never happen with a StringWriter"e);
     }
   }

  
 
   public static String delI(String id) {
     return TestHarness.deleteById(id);
   }
  
Generates a <delete>... XML string for an query

 
   public static String delQ(String q) {
     return TestHarness.deleteByQuery(q);
   }

  
Generates a simple <doc>... XML String with no options

Parameters:
fieldsAndValues 0th and Even numbered args are fields names, Odds are field values.
See also:
org.apache.solr.util.BaseTestHarness.makeSimpleDoc(java.lang.String[])
 
   public static XmlDoc doc(String... fieldsAndValues) {
     XmlDoc d = new XmlDoc();
     d.xml = TestHarness.makeSimpleDoc(fieldsAndValues);
     return d;
   }
 
   public static ModifiableSolrParams params(String... params) {
     for (int i=0; i<params.lengthi+=2) {
       msp.add(params[i], params[i+1]);
     }
     return msp;
   }
 
   public static Map map(Object... params) {
     LinkedHashMap ret = new LinkedHashMap();
     for (int i=0; i<params.lengthi+=2) {
       Object o = ret.put(params[i], params[i+1]);
       // TODO: handle multi-valued map?
     }
     return ret;
   }

  
Generates a SolrQueryRequest using the LocalRequestFactory

See also:
lrf
 
   public static SolrQueryRequest req(String... q) {
     return .makeRequest(q);
   }

  
Generates a SolrQueryRequest using the LocalRequestFactory

See also:
lrf
 
   public static SolrQueryRequest req(String[] paramsString... moreParams) {
     String[] allParams = moreParams;
     if (params.length!=0) {
      int len = params.length + moreParams.length;
      allParams = new String[len];
      System.arraycopy(params,0,allParams,0,params.length);
      System.arraycopy(moreParams,0,allParams,params.length,moreParams.length);
    }
    return .makeRequest(allParams);
  }

  
Generates a SolrQueryRequest
  public static SolrQueryRequest req(SolrParams paramsString... moreParams) {
    ModifiableSolrParams mp = new ModifiableSolrParams(params);
    for (int i=0; i<moreParams.lengthi+=2) {
      mp.add(moreParams[i], moreParams[i+1]);
    }
    return new LocalSolrQueryRequest(.getCore(), mp);
  }

  
Necessary to make method signatures un-ambiguous
  public static class XmlDoc {
    public String xml;
    @Override
    public String toString() { return ; }
  }

  
  public static boolean recurseDelete(File f) {
    try {
      TestUtil.rm(f);
      return true;
    } catch (IOException e) {
      ..println(e.toString());
      return false;
    }
  }
  
  public void clearIndex() {
    assertU(delQ("*:*"));
  }

  
Send JSON update commands
  public static String updateJ(String jsonSolrParams argsthrows Exception {
    SolrCore core = .getCore();
    if (args == null) {
      args = params("wt","json","indent","true");
    } else {
      ModifiableSolrParams newArgs = new ModifiableSolrParams(args);
      if (newArgs.get("wt") == nullnewArgs.set("wt","json");
      if (newArgs.get("indent") == nullnewArgs.set("indent","true");
      args = newArgs;
    }
    DirectSolrConnection connection = new DirectSolrConnection(core);
    SolrRequestHandler handler = core.getRequestHandler("/update/json");
    if (handler == null) {
      handler = new JsonUpdateRequestHandler();
      handler.init(null);
    }
    return connection.request(handlerargsjson);
  }
  public static SolrInputDocument sdoc(Object... fieldsAndValues) {
    for (int i=0; i<fieldsAndValues.lengthi+=2) {
      sd.addField((String)fieldsAndValues[i], fieldsAndValues[i+1]);
    }
    return sd;
  }
  public static List<SolrInputDocumentsdocs(SolrInputDocument... docs) {
    return Arrays.asList(docs);
  }

  
Converts "test JSON" and returns standard JSON. Currently this only consists of changing unescaped single quotes to double quotes, and escaped single quotes to single quotes. The primary purpose is to be able to easily embed JSON strings in a JAVA string with the best readability. This transformation is automatically applied to JSON test srings (like assertJQ).
  public static String json(String testJSON) {
    testJSON = .matcher(testJSON).replaceAll("\"");
    testJSON = .matcher(testJSON).replaceAll("'");
    return testJSON;
  }
  private static Pattern nonEscapedSingleQuotePattern = Pattern.compile("(?<!\\\\)\'");
  private static Pattern escapedSingleQuotePattern = Pattern.compile("\\\\\'");


  
Creates JSON from a SolrInputDocument. Doesn't currently handle boosts.

  public static String json(SolrInputDocument doc) {
    CharArr out = new CharArr();
    json(docout);
    return out.toString();
  }

  
Appends to the out array with JSON from the doc. Doesn't currently handle boosts, but does recursively handle child documents
  public static void json(SolrInputDocument docCharArr out) {
    try {
      out.append('{');
      boolean firstField = true;
      for (SolrInputField sfield : doc) {
        if (firstFieldfirstField=false;
        else out.append(',');
        JSONUtil.writeString(sfield.getName(), 0, sfield.getName().length(), out);
        out.append(':');
        if (sfield.getValueCount() > 1) {
          out.append('[');
          boolean firstVal = true;
          for (Object val : sfield) {
            if (firstValfirstVal=false;
            else out.append(',');
            out.append(JSONUtil.toJSON(val));
          }
          out.append(']');
        } else {
          out.append(JSONUtil.toJSON(sfield.getValue()));
        }
      }
      boolean firstChildDoc = true;
      if(doc.hasChildDocuments()) {
        out.append(",\"_childDocuments_\": [");
        List<SolrInputDocumentchildDocuments = doc.getChildDocuments();
        for(SolrInputDocument childDocument : childDocuments) {
          if (firstChildDocfirstChildDoc=false;
          else out.append(',');
          json(childDocumentout);
        }
        out.append(']');
      }
      out.append('}');
    } catch (IOException e) {
      // should never happen
    }
  }

  
Creates a JSON add command from a SolrInputDocument list. Doesn't currently handle boosts.
  public static String jsonAdd(SolrInputDocument... docs) {
    CharArr out = new CharArr();
    try {
      out.append('[');
      boolean firstField = true;
      for (SolrInputDocument doc : docs) {
        if (firstFieldfirstField=false;
        else out.append(',');
        out.append(json(doc));
      }
      out.append(']');
    } catch (IOException e) {
      // should never happen
    }
    return out.toString();
  }

    
Creates a JSON delete command from an id list
  public static String jsonDelId(Object... ids) {
    CharArr out = new CharArr();
    try {
      out.append('{');
      boolean first = true;
      for (Object id : ids) {
        if (firstfirst=false;
        else out.append(',');
        out.append("\"delete\":{\"id\":");
        out.append(JSONUtil.toJSON(id));
        out.append('}');
      }
      out.append('}');
    } catch (IOException e) {
      // should never happen
    }
    return out.toString();
  }


  
Creates a JSON deleteByQuery command
  public static String jsonDelQ(String... queries) {
    CharArr out = new CharArr();
    try {
      out.append('{');
      boolean first = true;
      for (Object q : queries) {
        if (firstfirst=false;
        else out.append(',');
        out.append("\"delete\":{\"query\":");
        out.append(JSONUtil.toJSON(q));