-
-
+ depends="compileTests, junit" />
+
+
+
@@ -143,7 +150,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tests failed!
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/java/org/apache/solr/request/SolrQueryRequest.java b/src/java/org/apache/solr/request/SolrQueryRequest.java
index f8c5fd3435f..0a78a7bcfe6 100644
--- a/src/java/org/apache/solr/request/SolrQueryRequest.java
+++ b/src/java/org/apache/solr/request/SolrQueryRequest.java
@@ -25,6 +25,10 @@ import org.apache.solr.core.SolrCore;
* @version $Id$
*/
public interface SolrQueryRequest {
+
+ /** All uses of this request are finished, resources can be freed */
+ public void close();
+
public String getParam(String name);
public String getQueryString();
diff --git a/src/java/org/apache/solr/util/AbstractSolrTestCase.java b/src/java/org/apache/solr/util/AbstractSolrTestCase.java
new file mode 100644
index 00000000000..34fc5c818e0
--- /dev/null
+++ b/src/java/org/apache/solr/util/AbstractSolrTestCase.java
@@ -0,0 +1,250 @@
+
+package org.apache.solr.util;
+
+import org.apache.solr.request.*;
+import org.apache.solr.util.TestHarness;
+
+import org.xml.sax.SAXException;
+import junit.framework.TestCase;
+import javax.xml.xpath.XPathExpressionException;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * An Abstract base class that makes writing Solr JUnit tests "easier"
+ *
+ *
+ * Test classes that subclass this need only specify the path to the
+ * schema.xml file (:TODO: the solrconfig.xml as well) and write some
+ * testMethods. This class takes care of creating/destroying the index,
+ * and provides several assert methods to assist you.
+ *
+ *
+ * @see #setUp
+ * @see #tearDown
+ */
+public abstract class AbstractSolrTestCase extends TestCase {
+
+ /**
+ * Harness initialized by initTestHarness.
+ *
+ *
+ * For use in test methods as needed.
+ *
+ */
+ protected TestHarness h;
+ /**
+ * LocalRequestFactory initialized by initTestHarness using sensible
+ * defaults.
+ *
+ *
+ * For use in test methods as needed.
+ *
+ */
+ protected TestHarness.LocalRequestFactory lrf;
+
+ /**
+ * Subclasses must define this method to return the path of the
+ * schema.xml they wish to use.
+ */
+ public abstract String getSchemaPath();
+
+ /**
+ * The directory used to story the index managed by the TestHarness h
+ */
+ protected File dataDir;
+
+ /**
+ * 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 void setUp() throws Exception {
+
+ dataDir = new File(System.getProperty("java.io.tmpdir")
+ + System.getProperty("file.separator")
+ + getClass().getName() + "-" + getName() + "-"
+ + System.currentTimeMillis());
+ dataDir.mkdirs();
+ h = new TestHarness(dataDir.getAbsolutePath(), getSchemaPath());
+ lrf = h.getRequestFactory
+ ("standard",0,20,"version","2.0");
+
+ }
+
+ /**
+ * Shuts down the test harness, and makes the best attempt possible
+ * to delete dataDir, unless the system property "solr.test.leavedatadir"
+ * is set.
+ */
+ public void tearDown() throws Exception {
+ h.close();
+ String skip = System.getProperty("solr.test.leavedatadir");
+ if (null != skip && 0 != skip.trim().length()) {
+ System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed: " + dataDir.getAbsolutePath());
+ } else {
+ if (!recurseDelete(dataDir)) {
+ System.err.println("!!!! WARNING: best effort to remove " + dataDir.getAbsolutePath() + " FAILED !!!!!");
+ }
+ }
+ }
+
+ /** Validates an update XML String is successful
+ */
+ public void assertU(String update) {
+ assertU(null, update);
+ }
+
+ /** Validates an update XML String is successful
+ */
+ public void assertU(String message, String update) {
+ try {
+ String m = (null == message) ? "" : message + " ";
+
+ String res = h.validateUpdate(update);
+ if (null != res) {
+ fail(m + "update was not successful: " + res);
+ }
+ } catch (SAXException e) {
+ throw new RuntimeException("Invalid XML", e);
+ }
+ }
+
+ /** Validates a query matches some XPath test expressions and closes the query */
+ public void assertQ(SolrQueryRequest req, String... tests) {
+ assertQ(null, req, tests);
+ }
+
+ /** Validates a query matches some XPath test expressions and closes the query */
+ public void assertQ(String message, SolrQueryRequest req, String... tests) {
+ try {
+ String m = (null == message) ? "" : message + " ";
+ String response = h.query(req);
+ String results = h.validateXPath(response, tests);
+ if (null != results) {
+ fail(m + "query failed XPath: " + results +
+ " xml response was: " + response);
+ }
+ } catch (XPathExpressionException e1) {
+ throw new RuntimeException("XPath is invalid", e1);
+ } catch (Exception e2) {
+ throw new RuntimeException("Exception during query", e2);
+ }
+ }
+
+ /**
+ * @see TestHarness#optimize
+ */
+ public String optimize(String... args) {
+ return h.optimize();
+ }
+ /**
+ * @see TestHarness#commit
+ */
+ public String commit(String... args) {
+ return h.commit();
+ }
+
+ /**
+ * Generates a simple <add><doc>... XML String with no options
+ *
+ * @param fieldsAndValues 0th and Even numbered args are fields names odds are field values.
+ * @see #add
+ * @see #doc
+ */
+ public String adoc(String... fieldsAndValues) {
+ Doc d = doc(fieldsAndValues);
+ return add(d);
+ }
+
+ /**
+ * Generates an <add><doc>... XML String with options
+ * on the add.
+ *
+ * @param doc the Document to add
+ * @param args 0th and Even numbered args are param names, Odds are param values.
+ * @see #add
+ * @see #doc
+ */
+ public String add(Doc doc, String... args) {
+ try {
+ StringWriter r = new StringWriter();
+
+ // this is anoying
+ if (null == args || 0 == args.length) {
+ r.write("");
+ r.write(doc.xml);
+ r.write("");
+ } 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);
+ }
+ }
+
+ /**
+ * Generates a <delete>... XML string for an ID
+ *
+ * @see TestHarness#deleteById
+ */
+ public String delI(String id) {
+ return h.deleteById(id);
+ }
+ /**
+ * Generates a <delete>... XML string for an query
+ *
+ * @see TestHarness#deleteByQuery
+ */
+ public String delQ(String q) {
+ return h.deleteByQuery(q);
+ }
+
+ /**
+ * Generates a simple <doc>... XML String with no options
+ *
+ * @param fieldsAndValues 0th and Even numbered args are fields names, Odds are field values.
+ * @see TestHarness#makeSimpleDoc
+ */
+ public Doc doc(String... fieldsAndValues) {
+ Doc d = new Doc();
+ d.xml = h.makeSimpleDoc(fieldsAndValues).toString();
+ return d;
+ }
+
+ /**
+ * Generates a SolrQueryRequest using the LocalRequestFactory
+ * @see #lrf
+ */
+ public SolrQueryRequest req( String q ) {
+ return lrf.makeRequest(q);
+ }
+
+ /** Neccessary to make method signatures un-ambiguous */
+ public static class Doc {
+ public String xml;
+ public String toString() { return xml; }
+ }
+
+ public static boolean recurseDelete(File f) {
+ if (f.isDirectory()) {
+ for (File sub : f.listFiles()) {
+ if (!recurseDelete(sub)) {
+ return false;
+ }
+ }
+ }
+ return f.delete();
+ }
+
+
+}
diff --git a/src/java/org/apache/solr/util/TestHarness.java b/src/java/org/apache/solr/util/TestHarness.java
new file mode 100644
index 00000000000..a1cf45e4072
--- /dev/null
+++ b/src/java/org/apache/solr/util/TestHarness.java
@@ -0,0 +1,372 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.util;
+
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.*;
+
+import org.xml.sax.SAXException;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathConstants;
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * This class provides a simple harness that may be usefull when
+ * writing testcasses.
+ *
+ *
+ * This class lives in the main source tree (and not in the test source
+ * tree) so that it will be included with even the most minimal solr
+ * distribution -- to encourage plugin writers to creat unit tests for their
+ * plugins.
+ *
+ * @author hossman
+ * @version $Id:$
+ */
+public class TestHarness {
+
+ private SolrCore core;
+ private XMLResponseWriter xmlwriter = new XMLResponseWriter();
+ private XPath xpath = XPathFactory.newInstance().newXPath();
+ private DocumentBuilder builder;
+
+ /**
+ * @param dataDirectory path for index data, will not be cleaned up
+ * @param schemaFile path of schema file
+ */
+ public TestHarness(String dataDirectory, String schemaFile) {
+ core = new SolrCore(dataDirectory, new IndexSchema(schemaFile));
+ try {
+ builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ /**
+ * Processes an "update" (add, commit or optimize) and
+ * returns the response as a String.
+ *
+ * @param xml The XML of the update
+ * @return The XML response to the update
+ */
+ public String update(String xml) {
+
+ StringReader req = new StringReader(xml);
+ StringWriter writer = new StringWriter(32000);
+ core.update(req, writer);
+ return writer.toString();
+
+ }
+
+
+ /**
+ * Validates that an "update" (add, commit or optimize) results in success.
+ *
+ * :TODO: currently only deals with one add/doc at a time, this will need changed if/when SOLR-2 is resolved
+ *
+ * @param xml The XML of the update
+ * @return null if succesful, otherwise the XML response to the update
+ */
+ public String validateUpdate(String xml) throws SAXException {
+ try {
+ String res = update(xml);
+ String valid = validateXPath(res, "//result[@status=0]" );
+ return (null == valid) ? null : res;
+ } catch (XPathExpressionException e) {
+ throw new RuntimeException
+ ("?!? static xpath has bug?", e);
+ }
+ }
+
+
+ /**
+ * Validates that an add of a single document results in success.
+ *
+ * @param fieldsAndValues Odds are field names, Evens are values
+ * @return null if succesful, otherwise the XML response to the update
+ * @see appendSimpleDoc
+ */
+ public String validateAddDoc(String... fieldsAndValues)
+ throws XPathExpressionException, SAXException, IOException {
+
+ StringBuffer buf = new StringBuffer();
+ buf.append("");
+ appendSimpleDoc(buf, fieldsAndValues);
+ buf.append("");
+
+ String res = update(buf.toString());
+ String valid = validateXPath(res, "//result[@status=0]" );
+ return (null == valid) ? null : res;
+ }
+
+
+
+ /**
+ * Validates a "query" response against an array of XPath test strings
+ *
+ * @param req the Query to process
+ * @return null if all good, otherwise the first test that fails.
+ * @exception Exception any exception in the response.
+ * @exception IOException if there is a problem writing the XML
+ * @see LocalSolrQueryRequest
+ */
+ public String validateQuery(SolrQueryRequest req, String... tests)
+ throws IOException, Exception {
+
+ String res = query(req);
+ return validateXPath(res, tests);
+ }
+
+ /**
+ * Processes a "query" using a user constructed SolrQueryRequest
+ *
+ * @param req the Query to process, will be closed.
+ * @return The XML response to the query
+ * @exception Exception any exception in the response.
+ * @exception IOException if there is a problem writing the XML
+ * @see LocalSolrQueryRequest
+ */
+ public String query(SolrQueryRequest req) throws IOException, Exception {
+
+ SolrQueryResponse rsp = new SolrQueryResponse();
+ core.execute(req,rsp);
+ if (rsp.getException() != null) {
+ throw rsp.getException();
+ }
+
+ StringWriter writer = new StringWriter(32000);
+ xmlwriter.write(writer,req,rsp);
+
+ req.close();
+
+ return writer.toString();
+ }
+
+
+ /**
+ * A helper method which valides a String against an array of XPath test
+ * strings.
+ *
+ * @param xml The xml String to validate
+ * @param tests Array of XPath strings to test (in boolean mode) on the xml
+ * @return null if all good, otherwise the first test that fails.
+ */
+ public String validateXPath(String xml, String... tests)
+ throws XPathExpressionException, SAXException {
+
+ if (tests==null || tests.length == 0) return null;
+
+ Document document=null;
+ try {
+ document = builder.parse(new ByteArrayInputStream
+ (xml.getBytes("UTF-8")));
+ } catch (UnsupportedEncodingException e1) {
+ throw new RuntimeException("Totally weird UTF-8 exception", e1);
+ } catch (IOException e2) {
+ throw new RuntimeException("Totally weird io exception", e2);
+ }
+
+ for (String xp : tests) {
+ xp=xp.trim();
+ Boolean bool = (Boolean) xpath.evaluate(xp, document,
+ XPathConstants.BOOLEAN);
+
+ if (!bool) {
+ return xp;
+ }
+ }
+ return null;
+
+ }
+
+ public SolrCore getCore() {
+ return core;
+ }
+
+ /**
+ * Shuts down and frees any resources
+ */
+ public void close() {
+ core.close();
+ }
+
+ /**
+ * A helper that adds an xml <doc> containing all of the
+ * fields and values specified (odds are fields, evens are values)
+ * to a StringBuffer.
+ */
+ public void appendSimpleDoc(StringBuffer buf, String... fieldsAndValues)
+ throws IOException {
+
+ buf.append(makeSimpleDoc(fieldsAndValues));
+ }
+ /**
+ * A helper that creates an xml <doc> containing all of the
+ * fields and values specified
+ *
+ * @param fieldsAndValues 0 and Even numbered args are fields names odds are field values.
+ */
+ public static StringBuffer makeSimpleDoc(String... fieldsAndValues) {
+
+ try {
+ StringWriter w = new StringWriter();
+ w.append("");
+ for (int i = 0; i < fieldsAndValues.length; i+=2) {
+ XML.writeXML(w, "field", fieldsAndValues[i+1], "name",
+ fieldsAndValues[i]);
+ }
+ w.append("");
+ return w.getBuffer();
+ } catch (IOException e) {
+ throw new RuntimeException
+ ("this should never happen with a StringWriter", e);
+ }
+ }
+
+ /**
+ * Generates a delete by query xml string
+ * @param q Query that has not already been xml escaped
+ */
+ public static String deleteByQuery(String q) {
+ return delete("query", q);
+ }
+ /**
+ * Generates a delete by id xml string
+ * @param id ID that has not already been xml escaped
+ */
+ public static String deleteById(String id) {
+ return delete("id", id);
+ }
+
+ /**
+ * Generates a delete xml string
+ * @param val text that has not already been xml escaped
+ */
+ private static String delete(String deltype, String val) {
+ try {
+ StringWriter r = new StringWriter();
+
+ r.write("");
+ XML.writeXML(r, deltype, val);
+ r.write("");
+
+ return r.getBuffer().toString();
+ } catch (IOException e) {
+ throw new RuntimeException
+ ("this should never happen with a StringWriter", e);
+ }
+ }
+
+ /**
+ * Helper that returns an <optimize> String with
+ * optional key/val pairs.
+ *
+ * @param args 0 and Even numbered args are params, Odd numbered args are values.
+ */
+ public static String optimize(String... args) {
+ return simpleTag("optimize", args);
+ }
+
+ private static String simpleTag(String tag, String... args) {
+ try {
+ StringWriter r = new StringWriter();
+
+ // this is anoying
+ if (null == args || 0 == args.length) {
+ XML.writeXML(r, tag, null);
+ } else {
+ XML.writeXML(r, tag, null, (Object)args);
+ }
+ return r.getBuffer().toString();
+ } catch (IOException e) {
+ throw new RuntimeException
+ ("this should never happen with a StringWriter", e);
+ }
+ }
+
+ /**
+ * Helper that returns an <commit> String with
+ * optional key/val pairs.
+ *
+ * @param args 0 and Even numbered args are params, Odd numbered args are values.
+ */
+ public static String commit(String... args) {
+ return simpleTag("commit", args);
+ }
+
+ public LocalRequestFactory getRequestFactory(String qtype,
+ int start,
+ int limit) {
+ LocalRequestFactory f = new LocalRequestFactory();
+ f.qtype = qtype;
+ f.start = start;
+ f.limit = limit;
+ return f;
+ }
+
+ /**
+ * 0 and Even numbered args are keys, Odd numbered args are values.
+ */
+ public LocalRequestFactory getRequestFactory(String qtype,
+ int start, int limit,
+ String... args) {
+ LocalRequestFactory f = getRequestFactory(qtype, start, limit);
+ for (int i = 0; i < args.length; i+=2) {
+ f.args.put(args[i], args[i+1]);
+ }
+ return f;
+
+ }
+
+ public LocalRequestFactory getRequestFactory(String qtype,
+ int start, int limit,
+ Map args) {
+
+ LocalRequestFactory f = getRequestFactory(qtype, start, limit);
+ f.args.putAll(args);
+ return f;
+ }
+
+ /**
+ * A Factory that generates LocalSolrQueryRequest objects using a
+ * specified set of default options.
+ */
+ public class LocalRequestFactory {
+ public String qtype = "standard";
+ public int start = 0;
+ public int limit = 1000;
+ public Map args = new HashMap();
+ public LocalRequestFactory() {
+ }
+ public LocalSolrQueryRequest makeRequest(String q) {
+ return new LocalSolrQueryRequest(TestHarness.this.getCore(),
+ q, qtype, start, limit, args);
+ }
+ }
+}
diff --git a/src/java/org/apache/solr/util/XML.java b/src/java/org/apache/solr/util/XML.java
index daf9d48a77b..02592358e9c 100644
--- a/src/java/org/apache/solr/util/XML.java
+++ b/src/java/org/apache/solr/util/XML.java
@@ -121,6 +121,29 @@ public class XML {
}
}
+ /** does NOT escape character data in val, must already be valid XML */
+ public final static void writeUnescapedXML(Writer out, String tag, String val, Object... attrs) throws IOException {
+ out.write('<');
+ out.write(tag);
+ for (int i=0; i");
+ } else {
+ out.write('>');
+ out.write(val);
+ out.write("");
+ out.write(tag);
+ out.write('>');
+ }
+ }
+
+ /** escapes character data in val */
public final static void writeXML(Writer out, String tag, String val, Object... attrs) throws IOException {
out.write('<');
out.write(tag);
diff --git a/src/test/org/apache/solr/BasicFunctionalityTest.java b/src/test/org/apache/solr/BasicFunctionalityTest.java
new file mode 100644
index 00000000000..0ebb3ea1c5a
--- /dev/null
+++ b/src/test/org/apache/solr/BasicFunctionalityTest.java
@@ -0,0 +1,163 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.request.*;
+import org.apache.solr.util.*;
+
+/**
+ * Tests some basic functionality of Solr while demonstrating good
+ * Best Practices for using AbstractSolrTestCase
+ */
+public class BasicFunctionalityTest extends AbstractSolrTestCase {
+
+ public String getSchemaPath() { return "solr/conf/schema.xml"; }
+
+ public void setUp() throws Exception {
+ // if you override setUp or tearDown, you better call
+ // the super classes version
+ super.setUp();
+ }
+ public void tearDown() throws Exception {
+ // if you override setUp or tearDown, you better call
+ // the super classes version
+ super.tearDown();
+
+ }
+
+ public void testSomeStuff() throws Exception {
+
+ assertQ("test query on empty index",
+ req("qlkciyopsbgzyvkylsjhchghjrdf")
+ ,"//result[@numFound='0']"
+ );
+
+ // test escaping of ";"
+ assertU("deleting 42 for no reason at all",
+ delI("42"));
+ assertU("adding doc#42",
+ adoc("id", "42", "val_s", "aa;bb"));
+ assertU("does commit work?",
+ commit());
+
+ assertQ("backslash escaping semicolon",
+ req("id:42 AND val_s:aa\\;bb")
+ ,"//*[@numFound='1']"
+ ,"//int[@name='id'][.='42']"
+ );
+
+ assertQ("quote escaping semicolon",
+ req("id:42 AND val_s:\"aa;bb\"")
+ ,"//*[@numFound='1']"
+ ,"//int[@name='id'][.='42']"
+ );
+
+ assertQ("no escaping semicolon",
+ req("id:42 AND val_s:aa")
+ ,"//*[@numFound='0']"
+ );
+
+ assertU(delI("42"));
+ assertU(commit());
+ assertQ(req("id:42")
+ ,"//*[@numFound='0']"
+ );
+
+ // test allowDups default of false
+
+ assertU(adoc("id", "42", "val_s", "AAA"));
+ assertU(adoc("id", "42", "val_s", "BBB"));
+ assertU(commit());
+ assertQ(req("id:42")
+ ,"//*[@numFound='1']"
+ ,"//str[.='BBB']"
+ );
+ assertU(adoc("id", "42", "val_s", "CCC"));
+ assertU(adoc("id", "42", "val_s", "DDD"));
+ assertU(commit());
+ assertQ(req("id:42")
+ ,"//*[@numFound='1']"
+ ,"//str[.='DDD']"
+ );
+
+ // test deletes
+ String [] adds = new String[] {
+ add( doc("id","101"), "allowDups", "false" ),
+ add( doc("id","101"), "allowDups", "false" ),
+ add( doc("id","105"), "allowDups", "true" ),
+ add( doc("id","102"), "allowDups", "false" ),
+ add( doc("id","103"), "allowDups", "true" ),
+ add( doc("id","101"), "allowDups", "false" ),
+ };
+ for (String a : adds) {
+ assertU(a, a);
+ }
+ assertU(commit());
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='4']"
+ );
+ assertU(delI("102"));
+ assertU(commit());
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='3']"
+ );
+ assertU(delI("105"));
+ assertU(commit());
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='2']"
+ );
+ assertU(delQ("id:[100 TO 110]"));
+ assertU(commit());
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='0']"
+ );
+ }
+
+
+ public void testMultipleUpdatesPerAdd() {
+
+ // big freaking kludge since the response is currently not well formed.
+ String res = h.update("12");
+ assertEquals("", res);
+ assertU("");
+ assertQ(req("id:[0 TO 99]")
+ ,"//*[@numFound='2']"
+ );
+
+ }
+
+
+// /** this doesn't work, but if it did, this is how we'd test it. */
+// public void testOverwriteFalse() {
+
+// assertU(adoc("id", "overwrite", "val_s", "AAA"));
+// assertU(commit());
+
+// assertU(add(doc("id", "overwrite", "val_s", "BBB")
+// ,"allowDups", "false"
+// ,"overwriteCommitted","false"
+// ,"overwritePending","false"
+// ));
+// assertU(commit());
+// assertQ(req("id:overwrite")
+// ,"//*[@numFound='1']"
+// ,"//str[.='AAA']"
+// );
+// }
+
+
+}
diff --git a/src/test/org/apache/solr/ConvertedLegacyTest.java b/src/test/org/apache/solr/ConvertedLegacyTest.java
new file mode 100644
index 00000000000..3c68eafce10
--- /dev/null
+++ b/src/test/org/apache/solr/ConvertedLegacyTest.java
@@ -0,0 +1,1296 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.request.*;
+import org.apache.solr.util.*;
+
+import java.util.*;
+import java.io.IOException;
+
+/**
+ * This tests was converted from a legacy testing system.
+ *
+ * it does not represent the best practices that should be used when
+ * writing Solr JUnit tests
+ */
+public class ConvertedLegacyTest extends AbstractSolrTestCase {
+
+ public String getSchemaPath() { return "solr/conf/schema.xml"; }
+
+ public void testABunchOfConvertedStuff() {
+ // these may be reused by things that need a special query
+ SolrQueryRequest req = null;
+ Map args = new HashMap();
+
+ // compact the index, keep things from getting out of hand
+
+ assertU("");
+
+ // test query
+
+ assertQ(req("qlkciyopsbgzyvkylsjhchghjrdf")
+ ,"//result[@numFound='0']"
+ );
+
+ // test escaping of ";"
+
+ assertU("42");
+ assertU("42aa;bb");
+ assertU("");
+ assertQ(req("id:42 AND val_s:aa\\;bb")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:42 AND val_s:\"aa;bb\"")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:42 AND val_s:\"aa\"")
+ ,"//*[@numFound='0']"
+ );
+
+
+
+ // test allowDups default of false
+
+ assertU("42");
+ assertU("42AAA");
+ assertU("42BBB");
+ assertU("");
+ assertQ(req("id:42")
+ ,"//*[@numFound='1'] "
+ ,"//str[.='BBB']"
+ );
+ assertU("42CCC");
+ assertU("42DDD");
+ assertU("");
+ assertQ(req("id:42")
+ ,"//*[@numFound='1'] "
+ ,"//str[.='DDD']"
+ );
+ assertU("42");
+
+ // test deletes
+
+ assertU("id:[100 TO 110]");
+ assertU("101");
+ assertU("101");
+ assertU("105");
+ assertU("102");
+ assertU("103");
+ assertU("101");
+ assertU("");
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='4']"
+ );
+ assertU("102");
+ assertU("");
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='3']"
+ );
+ assertU("id:105");
+ assertU("");
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='2']"
+ );
+ assertU("id:[100 TO 110]");
+ assertU("");
+ assertQ(req("id:[100 TO 110]")
+ ,"//*[@numFound='0']"
+ );
+
+ // test range
+
+ assertU("44");
+ assertU("44apple");
+ assertU("44banana");
+ assertU("44pear");
+ assertU("");
+ assertQ(req("val_s:[a TO z]")
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=3] "
+ ,"//*[@start='0']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 2, 5 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=1] "
+ ,"*//doc[1]/str[.='pear'] "
+ ,"//*[@start='2']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 3, 5 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 4, 5 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 25, 5 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 0, 1 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=1] "
+ ,"*//doc[1]/str[.='apple']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 0, 2 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=2] "
+ ,"*//doc[2]/str[.='banana']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 1, 1 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=1] "
+ ,"*//doc[1]/str[.='banana']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 3, 1 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 4, 1 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 1, 0 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
+ "standard", 0, 0 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z];val_s asc",
+ "standard", 0, 0 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z];val_s desc",
+ "standard", 0, 0 , args);
+ assertQ(req
+ ,"//*[@numFound='3'] "
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("val_s:[a TO b]")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("val_s:[a TO cat]")
+ ,"//*[@numFound='2']"
+ );
+ assertQ(req("val_s:[a TO *]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:[* TO z]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:[* TO *]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:[apple TO pear]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:[bear TO boar]")
+ ,"//*[@numFound='0']"
+ );
+ assertQ(req("val_s:[a TO a]")
+ ,"//*[@numFound='0']"
+ );
+ assertQ(req("val_s:[apple TO apple]")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("val_s:{apple TO pear}")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("val_s:{a TO z}")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:{* TO *}")
+ ,"//*[@numFound='3']"
+ );
+ // test rangequery within a boolean query
+
+ assertQ(req("id:44 AND val_s:[a TO z]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("id:44 OR val_s:[a TO z]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:[a TO b] OR val_s:[b TO z]")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("+val_s:[a TO b] -val_s:[b TO z]")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("-val_s:[a TO b] +val_s:[b TO z]")
+ ,"//*[@numFound='2']"
+ );
+ assertQ(req("val_s:[a TO c] AND val_s:[apple TO z]")
+ ,"//*[@numFound='2']"
+ );
+ assertQ(req("val_s:[a TO c] AND val_s:[a TO apple]")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:44 AND (val_s:[a TO c] AND val_s:[a TO apple])")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("(val_s:[apple TO apple] OR val_s:[a TO c]) AND (val_s:[b TO c] OR val_s:[b TO b])")
+ ,"//*[@numFound='1'] "
+ ,"//str[.='banana']"
+ );
+ assertQ(req("(val_s:[apple TO apple] AND val_s:[a TO c]) OR (val_s:[p TO z] AND val_s:[a TO z])")
+ ,"//*[@numFound='2'] "
+ ,"//str[.='apple'] "
+ ,"//str[.='pear']"
+ );
+
+ // check for docs that appear more than once in a range
+
+ assertU("44applebanana");
+ assertU("");
+ assertQ(req("val_s:[* TO *] OR val_s:[* TO *]")
+ ,"//*[@numFound='4']"
+ );
+ assertQ(req("val_s:[* TO *] AND val_s:[* TO *]")
+ ,"//*[@numFound='4']"
+ );
+ assertQ(req("val_s:[* TO *]")
+ ,"//*[@numFound='4']"
+ );
+
+
+ // 44
+
+ assertU("44red riding hood");
+ assertU("");
+ assertQ(req("id:44 AND red")
+ ,"//@numFound[.='1'] "
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:44 AND ride")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("id:44 AND blue")
+ ,"//@numFound[.='0']"
+ );
+
+ // allow duplicates
+
+ assertU("44");
+ assertU("44red riding hood");
+ assertU("44big bad wolf");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//@numFound[.='2']"
+ );
+ assertQ(req("id:44 AND red")
+ ,"//@numFound[.='1'] "
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:44 AND wolf")
+ ,"//@numFound[.='1'] "
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("+id:44 red wolf")
+ ,"//@numFound[.='2']"
+ );
+
+ // test removal of multiples w/o adding anything else
+
+ assertU("44");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//@numFound[.='0']"
+ );
+
+ // untokenized string type
+
+ assertU("44");
+ assertU("44and a 10.4 ?");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//str[.='and a 10.4 ?']"
+ );
+ assertU("44");
+ assertU("44abc123");
+ assertU("");
+ // TODO: how to search for something with spaces....
+
+ assertQ(req("sind:abc123")
+ ,"//@numFound[.='1'] "
+ ,"*[count(//@name[.='sind'])=0] "
+ ,"*[count(//@name[.='id'])=1]"
+ );
+
+ assertU("44");
+ assertU("44");
+ assertU("44abc123");
+ assertU("");
+ // TODO: how to search for something with spaces....
+
+ assertQ(req("sindsto:abc123")
+ ,"//str[.='abc123']"
+ );
+
+ // test output of multivalued fields
+
+ assertU("44");
+ assertU("44yonik3yonik4");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//arr[@name='title'][./str='yonik3' and ./str='yonik4'] "
+ ,"*[count(//@name[.='title'])=1]"
+ );
+ assertQ(req("title:yonik3")
+ ,"//@numFound[.>'0']"
+ );
+ assertQ(req("title:yonik4")
+ ,"//@numFound[.>'0']"
+ );
+ assertQ(req("title:yonik5")
+ ,"//@numFound[.='0']"
+ );
+ assertU("title:yonik4");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//@numFound[.='0']"
+ );
+
+
+ // not visible until commit
+
+ assertU("44");
+ assertU("");
+ assertU("44");
+ assertQ(req("id:44")
+ ,"//@numFound[.='0']"
+ );
+ assertU("");
+ assertQ(req("id:44")
+ ,"//@numFound[.='1']"
+ );
+
+ // test configurable stop words
+
+ assertU("44");
+ assertU("44world stopworda view");
+ assertU("");
+ assertQ(req("+id:44 +teststop:world")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("teststop:stopworda")
+ ,"//@numFound[.='0']"
+ );
+
+ // test ignoreCase stop words
+
+ assertU("44");
+ assertU("44world AnD view");
+ assertU("");
+ assertQ(req("+id:44 +stopfilt:world")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("stopfilt:\"and\"")
+ ,"//@numFound[.='0']"
+ );
+ assertQ(req("stopfilt:\"AND\"")
+ ,"//@numFound[.='0']"
+ );
+ assertQ(req("stopfilt:\"AnD\"")
+ ,"//@numFound[.='0']"
+ );
+
+ // test dynamic field types
+
+ assertU("44");
+ assertU("4451778cats");
+ assertU("");
+ // test if the dyn fields got added
+
+ assertQ(req("id:44")
+ ,"*[count(//doc/*)>=3] "
+ ,"//int[@name='gack_i'][.='51778'] "
+ ,"//str[@name='t_name'][.='cats']"
+ );
+ // now test if we can query by a dynamic field (requires analyzer support)
+
+ assertQ(req("t_name:cat")
+ ,"//str[@name='t_name' and .='cats']"
+ );
+ // check that deleteByQuery works for dynamic fields
+
+ assertU("t_name:cat");
+ assertU("");
+ assertQ(req("t_name:cat")
+ ,"//@numFound[.='0']"
+ );
+
+ // test that longest dynamic field match happens first
+
+ assertU("44mystr12321");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//str[@name='xaa'][.='mystr'] "
+ ,"//int[@name='xaaa'][.='12321']"
+ );
+
+
+ // test integer ranges and sorting
+
+ assertU("44");
+ assertU("441234567890");
+ assertU("4410");
+ assertU("441");
+ assertU("442");
+ assertU("4415");
+ assertU("44-1");
+ assertU("44-987654321");
+ assertU("442147483647");
+ assertU("44-2147483648");
+ assertU("440");
+ assertU("");
+ assertQ(req("id:44")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_i:2147483647")
+ ,"//@numFound[.='1'] "
+ ,"//int[.='2147483647']"
+ );
+ assertQ(req("num_i:\"-2147483648\"")
+ ,"//@numFound[.='1'] "
+ ,"//int[.='-2147483648']"
+ );
+ assertQ(req("id:44;num_i asc;")
+ ,"//doc[1]/int[.='-2147483648'] "
+ ,"//doc[last()]/int[.='2147483647']"
+ );
+ assertQ(req("id:44;num_i desc;")
+ ,"//doc[1]/int[.='2147483647'] "
+ ,"//doc[last()]/int[.='-2147483648']"
+ );
+ assertQ(req("num_i:[0 TO 9]")
+ ,"*[count(//doc)=3]"
+ );
+ assertQ(req("num_i:[-2147483648 TO 2147483647]")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_i:[-10 TO -1]")
+ ,"*[count(//doc)=1]"
+ );
+
+ // test long ranges and sorting
+
+ assertU("44");
+ assertU("441234567890");
+ assertU("4410");
+ assertU("441");
+ assertU("442");
+ assertU("4415");
+ assertU("44-1");
+ assertU("44-987654321");
+ assertU("449223372036854775807");
+ assertU("44-9223372036854775808");
+ assertU("440");
+ assertU("");
+ assertQ(req("id:44")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_l:9223372036854775807")
+ ,"//@numFound[.='1'] "
+ ,"//long[.='9223372036854775807']"
+ );
+ assertQ(req("num_l:\"-9223372036854775808\"")
+ ,"//@numFound[.='1'] "
+ ,"//long[.='-9223372036854775808']"
+ );
+ assertQ(req("id:44;num_l asc;")
+ ,"//doc[1]/long[.='-9223372036854775808'] "
+ ,"//doc[last()]/long[.='9223372036854775807']"
+ );
+ assertQ(req("id:44;num_l desc;")
+ ,"//doc[1]/long[.='9223372036854775807'] "
+ ,"//doc[last()]/long[.='-9223372036854775808']"
+ );
+ assertQ(req("num_l:[-1 TO 9]")
+ ,"*[count(//doc)=4]"
+ );
+ assertQ(req("num_l:[-9223372036854775808 TO 9223372036854775807]")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_l:[-10 TO -1]")
+ ,"*[count(//doc)=1]"
+ );
+
+ // test binary float ranges and sorting
+
+ assertU("44");
+ assertU("441.4142135");
+ assertU("44Infinity");
+ assertU("44-Infinity");
+ assertU("44NaN");
+ assertU("442");
+ assertU("44-1");
+ assertU("44-987654321");
+ assertU("44-999999.99");
+ assertU("44-1e20");
+ assertU("440");
+ assertU("");
+ assertQ(req("id:44")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_f:Infinity")
+ ,"//@numFound[.='1'] "
+ ,"//float[.='Infinity']"
+ );
+ assertQ(req("num_f:\"-Infinity\"")
+ ,"//@numFound[.='1'] "
+ ,"//float[.='-Infinity']"
+ );
+ assertQ(req("num_f:\"NaN\"")
+ ,"//@numFound[.='1'] "
+ ,"//float[.='NaN']"
+ );
+ assertQ(req("num_f:\"-1e20\"")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("id:44;num_f asc;")
+ ,"//doc[1]/float[.='-Infinity'] "
+ ,"//doc[last()]/float[.='NaN']"
+ );
+ assertQ(req("id:44;num_f desc;")
+ ,"//doc[1]/float[.='NaN'] "
+ ,"//doc[last()]/float[.='-Infinity']"
+ );
+ assertQ(req("num_f:[-1 TO 2]")
+ ,"*[count(//doc)=4]"
+ );
+ assertQ(req("num_f:[-Infinity TO Infinity]")
+ ,"*[count(//doc)=9]"
+ );
+
+
+
+ // test binary double ranges and sorting
+
+ assertU("44");
+ assertU("441.4142135");
+ assertU("44Infinity");
+ assertU("44-Infinity");
+ assertU("44NaN");
+ assertU("442");
+ assertU("44-1");
+ assertU("441e-100");
+ assertU("44-999999.99");
+ assertU("44-1e100");
+ assertU("440");
+ assertU("");
+ assertQ(req("id:44")
+ ,"*[count(//doc)=10]"
+ );
+ assertQ(req("num_d:Infinity")
+ ,"//@numFound[.='1'] "
+ ,"//double[.='Infinity']"
+ );
+ assertQ(req("num_d:\"-Infinity\"")
+ ,"//@numFound[.='1'] "
+ ,"//double[.='-Infinity']"
+ );
+ assertQ(req("num_d:\"NaN\"")
+ ,"//@numFound[.='1'] "
+ ,"//double[.='NaN']"
+ );
+ assertQ(req("num_d:\"-1e100\"")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("num_d:\"1e-100\"")
+ ,"//@numFound[.='1']"
+ );
+ assertQ(req("id:44;num_d asc;")
+ ,"//doc[1]/double[.='-Infinity'] "
+ ,"//doc[last()]/double[.='NaN']"
+ );
+ assertQ(req("id:44;num_d desc;")
+ ,"//doc[1]/double[.='NaN'] "
+ ,"//doc[last()]/double[.='-Infinity']"
+ );
+ assertQ(req("num_d:[-1 TO 2]")
+ ,"*[count(//doc)=5]"
+ );
+ assertQ(req("num_d:[-Infinity TO Infinity]")
+ ,"*[count(//doc)=9]"
+ );
+
+
+ // test sorting on multiple fields
+
+ assertU("44");
+ assertU("4410");
+ assertU("441100");
+ assertU("44-1");
+ assertU("4415");
+ assertU("44150");
+ assertU("440");
+ assertU("");
+ assertQ(req("id:44")
+ ,"*[count(//doc)=6]"
+ );
+
+ assertQ(req("id:44; a_i asc,b_i desc")
+ ,"*[count(//doc)=6] "
+ ,"//doc[3]/int[.='100'] "
+ ,"//doc[4]/int[.='50']"
+ );
+ assertQ(req("id:44;a_i asc , b_i asc;")
+ ,"*[count(//doc)=6] "
+ ,"//doc[3]/int[.='50'] "
+ ,"//doc[4]/int[.='100']"
+ );
+ assertQ(req("id:44;a_i asc;")
+ ,"*[count(//doc)=6] "
+ ,"//doc[1]/int[.='-1'] "
+ ,"//doc[last()]/int[.='15']"
+ );
+ assertQ(req("id:44;a_i asc , score top;")
+ ,"*[count(//doc)=6] "
+ ,"//doc[1]/int[.='-1'] "
+ ,"//doc[last()]/int[.='15']"
+ );
+ assertQ(req("id:44; score top , a_i top, b_i bottom ;")
+ ,"*[count(//doc)=6] "
+ ,"//doc[last()]/int[.='-1'] "
+ ,"//doc[1]/int[.='15'] "
+ ,"//doc[3]/int[.='50'] "
+ ,"//doc[4]/int[.='100']"
+ );
+
+
+ // test sorting with some docs missing the sort field
+
+ assertU("id_i:[1000 TO 1010]");
+ assertU("10001");
+ assertU("100110");
+ assertU("10021100");
+ assertU("1003-1");
+ assertU("100415");
+ assertU("1005150");
+ assertU("10060");
+ assertU("");
+ assertQ(req("id_i:[1000 TO 1010]")
+ ,"*[count(//doc)=7]"
+ );
+ assertQ(req("id_i:[1000 TO 1010]; b_i asc")
+ ,"*[count(//doc)=7] "
+ ,"//doc[1]/int[.='50'] "
+ ,"//doc[2]/int[.='100']"
+ );
+ assertQ(req("id_i:[1000 TO 1010]; b_i desc")
+ ,"*[count(//doc)=7] "
+ ,"//doc[1]/int[.='100'] "
+ ,"//doc[2]/int[.='50']"
+ );
+ assertQ(req("id_i:[1000 TO 1010]; a_i asc,b_i desc")
+ ,"*[count(//doc)=7] "
+ ,"//doc[3]/int[.='100'] "
+ ,"//doc[4]/int[.='50'] "
+ ,"//doc[5]/int[.='1000']"
+ );
+ assertQ(req("id_i:[1000 TO 1010]; a_i asc,b_i asc")
+ ,"*[count(//doc)=7] "
+ ,"//doc[3]/int[.='50'] "
+ ,"//doc[4]/int[.='100'] "
+ ,"//doc[5]/int[.='1000']"
+ );
+
+
+ // test prefix query
+
+ assertU("val_s:[* TO *]");
+ assertU("100apple");
+ assertU("101banana");
+ assertU("102apple");
+ assertU("103pearing");
+ assertU("104pear");
+ assertU("105appalling");
+ assertU("106pearson");
+ assertU("107port");
+ assertU("");
+
+ assertQ(req("val_s:a*")
+ ,"//*[@numFound='3']"
+ );
+ assertQ(req("val_s:p*")
+ ,"//*[@numFound='4']"
+ );
+ // val_s:* %//*[@numFound="8"]
+
+
+ assertU("id:[100 TO 110]");
+
+ // test copyField functionality
+
+ assertU("42How Now4 brown Cows");
+ assertU("");
+ assertQ(req("id:42 AND title:Now")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND title_lettertok:Now")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND title:cow")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND title_stemmed:cow")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND text:cow")
+ ,"*[count(//doc)=1]"
+ );
+
+ // test slop
+
+ assertU("42foo bar");
+ assertU("");
+ assertQ(req("id:42 AND text:\"foo bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND text:\"foo\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND text:\"bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND text:\"bar foo\"")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND text:\"bar foo\"~2")
+ ,"*[count(//doc)=1]"
+ );
+
+
+ // intra-word delimiter testing (WordDelimiterFilter)
+
+ assertU("42foo bar");
+ assertU("");
+ assertQ(req("id:42 AND subword:\"foo bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"foo\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"bar foo\"")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND subword:\"bar foo\"~2")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"foo/bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"foobar\"")
+ ,"*[count(//doc)=0]"
+ );
+
+ assertU("42foo-bar");
+ assertU("");
+ assertQ(req("id:42 AND subword:\"foo bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"foo\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"bar foo\"")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND subword:\"bar foo\"~2")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"foo/bar\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:foobar")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42Canon PowerShot SD500 7MP");
+ assertU("");
+ assertQ(req("id:42 AND subword:\"power-shot\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"power shot sd 500\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"powershot\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"SD-500\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"SD500\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"SD500-7MP\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"PowerShotSD500-7MP\"")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42Wi-Fi");
+ assertU("");
+ assertQ(req("id:42 AND subword:wifi")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:wi+=fi")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:wi+=fi")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:WiFi")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"wi fi\"")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42'I.B.M' A's,B's,C's");
+ assertU("");
+ assertQ(req("id:42 AND subword:\"'I.B.M.'\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:I.B.M")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:IBM")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:I--B--M")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"I B M\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:IBM's")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:IBM'sx")
+ ,"*[count(//doc)=0]"
+ );
+
+ // this one fails since IBM and ABC are separated by two tokens
+
+ // id:42 AND subword:IBM's-ABC's %*[count(//doc)=1]
+
+ assertQ(req("id:42 AND subword:\"IBM's-ABC's\"~2")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertQ(req("id:42 AND subword:\"A's B's-C's\"")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42Sony KDF-E50A10");
+ assertU("");
+
+ // check for exact match:
+
+ // Sony KDF E/KDFE 50 A 10 (this is how it's indexed)
+
+ // Sony KDF E 50 A 10 (and how it's queried)
+
+ assertQ(req("id:42 AND subword:\"Sony KDF-E50A10\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:10")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:Sony")
+ ,"*[count(//doc)=1]"
+ );
+
+ // this one fails without slop since Sony and KDFE have a token inbetween
+
+ // id:42 AND subword:SonyKDFE50A10 %*[count(//doc)=1]
+
+ assertQ(req("id:42 AND subword:\"SonyKDFE50A10\"~10")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertQ(req("id:42 AND subword:\"Sony KDF E-50-A-10\"")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42http://www.yahoo.com");
+ assertU("");
+ assertQ(req("id:42 AND subword:yahoo")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:www.yahoo.com")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:http://www.yahoo.com")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42--Q 1-- W2 E-3 Ok xY 4R 5-T *6-Y- 7-8-- 10A-B");
+ assertU("");
+ assertQ(req("id:42 AND subword:Q")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:1")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"w 2\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"e 3\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"o k\"")
+ ,"*[count(//doc)=0]"
+ );
+ assertQ(req("id:42 AND subword:\"ok\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"x y\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"xy\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"4 r\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"5 t\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"5 t\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"6 y\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"7 8\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"78\"")
+ ,"*[count(//doc)=1]"
+ );
+ assertQ(req("id:42 AND subword:\"10 A+B\"")
+ ,"*[count(//doc)=1]"
+ );
+
+ assertU("42FooBarBaz");
+ assertU("42FooBar10");
+ assertU("4210FooBar");
+ assertU("42BAZ");
+ assertU("4210");
+ assertU("42Mark, I found what's the problem! It turns to be from the latest schema. I found tons of exceptions in the resin.stdout that prevented the builder from performing. It's all coming from the WordDelimiterFilter which was just added to the latest schema: [2005-08-29 15:11:38.375] java.lang.IndexOutOfBoundsException: Index: 3, Size: 3 673804 [2005-08-29 15:11:38.375] at java.util.ArrayList.RangeCheck(ArrayList.java:547) 673805 [2005-08-29 15:11:38.375] at java.util.ArrayList.get(ArrayList.java:322) 673806 [2005-08-29 15:11:38.375] at solr.analysis.WordDelimiterFilter.addCombos(WordDelimiterFilter.java:349) 673807 [2005-08-29 15:11:38.375] at solr.analysis.WordDelimiterFilter.next(WordDelimiterFilter.java:325) 673808 [2005-08-29 15:11:38.375] at org.apache.lucene.analysis.LowerCaseFilter.next(LowerCaseFilter.java:32) 673809 [2005-08-29 15:11:38.375] at org.apache.lucene.analysis.StopFilter.next(StopFilter.java:98) 673810 [2005-08-29 15:11:38.375] at solr.EnglishPorterFilter.next(TokenizerFactory.java:163) 673811 [2005-08-29 15:11:38.375] at org.apache.lucene.index.DocumentWriter.invertDocument(DocumentWriter.java:143) 673812 [2005-08-29 15:11:38.375] at org.apache.lucene.index.DocumentWriter.addDocument(DocumentWriter.java:81) 673813 [2005-08-29 15:11:38.375] at org.apache.lucene.index.IndexWriter.addDocument(IndexWriter.java:307) 673814 [2005-08-29 15:11:38.375] at org.apache.lucene.index.IndexWriter.addDocument(IndexWriter.java:294) 673815 [2005-08-29 15:11:38.375] at solr.DirectUpdateHandler2.doAdd(DirectUpdateHandler2.java:170) 673816 [2005-08-29 15:11:38.375] at solr.DirectUpdateHandler2.overwriteBoth(DirectUpdateHandler2.java:317) 673817 [2005-08-29 15:11:38.375] at solr.DirectUpdateHandler2.addDoc(DirectUpdateHandler2.java:191) 673818 [2005-08-29 15:11:38.375] at solr.SolrCore.update(SolrCore.java:795) 673819 [2005-08-29 15:11:38.375] at solrserver.SolrServlet.doPost(SolrServlet.java:71) 673820 [2005-08-29 15:11:38.375] at javax.servlet.http.HttpServlet.service(HttpServlet.java:154) 673821 [2005-08-29 15:11:38.375] at javax.servlet.http.HttpServlet.service(HttpServlet.java:92) 673822 [2005-08-29 15:11:38.375] at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:99) 673823 [2005-08-29 15:11:38.375] at com.caucho.server.cache.CacheFilterChain.doFilter(CacheFilterChain.java:188) 673824 [2005-08-29 15:11:38.375] at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:163) 673825 [2005-08-29 15:11:38.375] at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:208) 673826 [2005-08-29 15:11:38.375] at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:259) 673827 [2005-08-29 15:11:38.375] at com.caucho.server.port.TcpConnection.run(TcpConnection.java:363) 673828 [2005-08-29 15:11:38.375] at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:490) 673829 [2005-08-29 15:11:38.375] at com.caucho.util.ThreadPool.run(ThreadPool.java:423) 673830 [2005-08-29 15:11:38.375] at java.lang.Thread.run(Thread.java:595) With the previous schema I'm able to perform a successful full build: http://c12-ssa-dev40-so-mas1.cnet.com:5078/select/?stylesheet=q=docTypeversion=2.0start=0rows=10indent=on Do you want to rollback to the previous schema version");
+
+
+ //
+
+ assertU("44");
+ assertU("44Yoniktrue10000000000software engineer1e1003.14159622005-03-18T01:14:34Z1.414213562.999");
+ assertU("");
+ assertQ(req("id:44")
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","fname_s,arr_f ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//str[.='Yonik'] "
+ ,"//float[.='1.4142135']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl"," ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//str[.='Yonik'] "
+ ,"//float[.='1.4142135']"
+ );
+
+ // test addition of score field
+
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//str[.='Yonik'] "
+ ,"//float[.='1.4142135'] "
+ ,"//float[@name='score'] "
+ ,"*[count(//doc/*)=10]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","*,score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//str[.='Yonik'] "
+ ,"//float[.='1.4142135'] "
+ ,"//float[@name='score'] "
+ ,"*[count(//doc/*)=10]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","* ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//str[.='Yonik'] "
+ ,"//float[.='1.4142135'] "
+ ,"*[count(//doc/*)>=9]"
+ );
+
+ // test maxScore
+
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//result[@maxScore>0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//result[@maxScore>0]"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44;",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//@maxScore = //doc/float[@name='score']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score ");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
+ "standard", 0, 10, args);
+ assertQ(req
+ ,"//@maxScore = //doc/float[@name='score']"
+ );
+ args = new HashMap();
+ args.put("version","2.0");
+ args.put("fl","score");
+ req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
+ "standard", 0, 0 , args);
+ assertQ(req
+ ,"//result[@maxScore>0]"
+ );
+
+
+ // test schema field attribute inheritance and overriding
+
+ assertU("44");
+ assertU("44hi");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//*[@name='shouldbestored']"
+ );
+ assertQ(req("+id:44 +shouldbestored:hi")
+ ,"//*[@numFound='1']"
+ );
+
+ assertU("44");
+ assertU("44hi");
+ assertU("");
+ assertQ(req("id:44")
+ ,"not(//*[@name='shouldbeunstored'])"
+ );
+ assertQ(req("+id:44 +shouldbeunstored:hi")
+ ,"//*[@numFound='1']"
+ );
+
+ assertU("44");
+ assertU("44hi");
+ assertU("");
+ assertQ(req("id:44")
+ ,"//*[@name='shouldbeunindexed']"
+ );
+ // this should result in an error... how to check for that?
+
+ // +id:44 +shouldbeunindexed:hi %//*[@numFound="0"]
+
+
+ // test spaces between XML elements because that can introduce extra XML events that
+
+ // can mess up parsing (and it has in the past)
+
+ assertU(" 44 ");
+ assertU(" 44 hi ");
+ assertU(" ");
+
+ // test adding multiple docs per add command
+
+ // assertU("id:[0 TO 99]");
+ // assertU("12");
+ // assertU("");
+ // assertQ(req("id:[0 TO 99]")
+ // ,"//*[@numFound='2']"
+ // );
+
+ // test synonym filter
+
+ assertU("id:[10 TO 100]");
+ assertU("10a");
+ assertU("11b");
+ assertU("12c");
+ assertU("13foo");
+ assertU("");
+ assertQ(req("id:10 AND syn:a")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:10 AND syn:aa")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:11 AND syn:b")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:11 AND syn:b1")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:11 AND syn:b2")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:12 AND syn:c")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:12 AND syn:c1")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:12 AND syn:c2")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:13 AND syn:foo")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:13 AND syn:bar")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("id:13 AND syn:baz")
+ ,"//*[@numFound='1']"
+ );
+
+
+ // test position increment gaps between field values
+
+ assertU("44");
+ assertU("45");
+ assertU("44aa bb ccdd ee ff");
+ assertU("45aa bb ccdd ee ff");
+ assertU("");
+ assertQ(req("+id:44 +textgap:\"aa bb cc\"")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("+id:44 +textgap:\"dd ee ff\"")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("+id:44 +textgap:\"cc dd\"")
+ ,"//*[@numFound='0']"
+ );
+ assertQ(req("+id:44 +textgap:\"cc dd\"~100")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("+id:44 +textgap:\"bb cc dd ee\"~90")
+ ,"//*[@numFound='0']"
+ );
+ assertQ(req("+id:44 +textgap:\"bb cc dd ee\"~100")
+ ,"//*[@numFound='1']"
+ );
+ assertQ(req("+id:45 +text:\"cc dd\"")
+ ,"//*[@numFound='1']"
+ );
+
+
+ // trigger output of custom value test
+
+ args = new HashMap();
+ args.put("version","2.0");
+ req = new LocalSolrQueryRequest(h.getCore(), "values",
+ "test", 0, 10, args);
+ assertQ(req
+ );
+
+ }
+}
diff --git a/src/test/org/apache/solr/SampleTest.java b/src/test/org/apache/solr/SampleTest.java
new file mode 100644
index 00000000000..5b481e10cf0
--- /dev/null
+++ b/src/test/org/apache/solr/SampleTest.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.request.*;
+import org.apache.solr.util.*;
+
+import java.util.*;
+import java.io.IOException;
+
+/**
+ * This is an example of how to write a JUnit tests for Solr using the
+ * AbstractSolrTestCase
+ */
+public class SampleTest extends AbstractSolrTestCase {
+
+ /**
+ * All subclasses of AbstractSolrTestCase must define this method
+ */
+ public String getSchemaPath() { return "solr/conf/schema.xml"; }
+
+ /**
+ * Demonstration of some of the simple ways to use the base class
+ */
+ public void testSimple() {
+
+ assertU("Simple assertion that adding a document works",
+ adoc("id", "4055",
+ "subject", "Hoss the Hoss man Hostetter"));
+
+ /* alternate syntax, no label */
+ assertU(adoc("id", "4056",
+ "subject", "Some Other Guy"));
+
+ assertU(commit());
+ assertU(optimize());
+
+ assertQ("couldn't find subject hoss",
+ req("subject:Hoss")
+ ,"//result[@numFound=1]"
+ ,"//int[@name='id'][.='4055']"
+ );
+ }
+
+ /**
+ * Demonstration of some of the more complex ways to use the base class
+ */
+ public void testAdvanced() throws Exception {
+
+ assertU("less common case, a complex addition with options",
+ add(doc("id", "4059",
+ "subject", "Who Me?"),
+ "allowDups", "true"));
+
+ assertU("or just make the raw XML yourself",
+ "" +
+ doc("id", "4059",
+ "subject", "Who Me Again?") + "");
+
+ // or really make the xml yourself
+ assertU("4055"
+ +"Hoss the Hoss man Hostetter"
+ +"");
+
+ assertU("");
+ assertU("");
+
+ /* access the default LocalRequestFactory directly to make a request */
+ SolrQueryRequest req = lrf.makeRequest( "subject:Hoss" );
+ assertQ("couldn't find subject hoss",
+ req
+ ,"//result[@numFound=1]"
+ ,"//int[@name='id'][.='4055']"
+ );
+
+ /* make your own LocalRequestFactory to build a request */
+ TestHarness.LocalRequestFactory l = h.getRequestFactory
+ ("standard",100,200,"version","2.1");
+ assertQ("how did i find Mack Daddy? ",
+ l.makeRequest( "Mack Daddy" )
+ ,"//result[@numFound=0]"
+ );
+
+ /* you can access the harness directly as well*/
+ assertNull("how did i find Mack Daddy? ",
+ h.validateQuery(l.makeRequest( "Mack Daddy" )
+ ,"//result[@numFound=0]"
+ ));
+
+ }
+}
+
+