| /* |
| * 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.lucene.queryparser.xml; |
| |
| import org.apache.lucene.analysis.Analyzer; |
| import org.apache.lucene.analysis.MockAnalyzer; |
| import org.apache.lucene.analysis.MockTokenFilter; |
| import org.apache.lucene.analysis.MockTokenizer; |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.index.IndexReader; |
| import org.apache.lucene.search.DisjunctionMaxQuery; |
| import org.apache.lucene.search.IndexSearcher; |
| import org.apache.lucene.search.Query; |
| import org.apache.lucene.search.ScoreDoc; |
| import org.apache.lucene.search.TopDocs; |
| import org.apache.lucene.search.spans.SpanQuery; |
| import org.apache.lucene.util.LuceneTestCase; |
| import org.junit.AfterClass; |
| import org.xml.sax.SAXException; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| |
| public class TestCoreParser extends LuceneTestCase { |
| |
| final private static String defaultField = "contents"; |
| |
| private static Analyzer analyzer; |
| private static CoreParser coreParser; |
| |
| private static CoreParserTestIndexData indexData; |
| |
| protected Analyzer newAnalyzer() { |
| // TODO: rewrite test (this needs to set QueryParser.enablePositionIncrements, too, for work with CURRENT): |
| return new MockAnalyzer(random(), MockTokenizer.WHITESPACE, true, MockTokenFilter.ENGLISH_STOPSET); |
| } |
| |
| protected CoreParser newCoreParser(String defaultField, Analyzer analyzer) { |
| return new CoreParser(defaultField, analyzer); |
| } |
| |
| @AfterClass |
| public static void afterClass() throws Exception { |
| if (indexData != null) { |
| indexData.close(); |
| indexData = null; |
| } |
| coreParser = null; |
| analyzer = null; |
| } |
| |
| public void testTermQueryXML() throws ParserException, IOException { |
| Query q = parse("TermQuery.xml"); |
| dumpResults("TermQuery", q, 5); |
| } |
| |
| public void test_DOCTYPE_TermQueryXML() throws ParserException, IOException { |
| SAXException saxe = LuceneTestCase.expectThrows(ParserException.class, SAXException.class, |
| () -> parse("DOCTYPE_TermQuery.xml")); |
| assertTrue(saxe.getMessage().startsWith("External Entity resolving unsupported:")); |
| } |
| |
| public void test_ENTITY_TermQueryXML() throws ParserException, IOException { |
| SAXException saxe = LuceneTestCase.expectThrows(ParserException.class, SAXException.class, |
| () -> parse("ENTITY_TermQuery.xml")); |
| assertTrue(saxe.getMessage().startsWith("External Entity resolving unsupported:")); |
| } |
| |
| public void testTermQueryEmptyXML() throws ParserException, IOException { |
| parseShouldFail("TermQueryEmpty.xml", |
| "TermQuery has no text"); |
| } |
| |
| public void testTermsQueryXML() throws ParserException, IOException { |
| Query q = parse("TermsQuery.xml"); |
| dumpResults("TermsQuery", q, 5); |
| } |
| |
| public void testBooleanQueryXML() throws ParserException, IOException { |
| Query q = parse("BooleanQuery.xml"); |
| dumpResults("BooleanQuery", q, 5); |
| } |
| |
| public void testDisjunctionMaxQueryXML() throws ParserException, IOException { |
| Query q = parse("DisjunctionMaxQuery.xml"); |
| assertTrue(q instanceof DisjunctionMaxQuery); |
| DisjunctionMaxQuery d = (DisjunctionMaxQuery)q; |
| assertEquals(0.0f, d.getTieBreakerMultiplier(), 0.0001f); |
| assertEquals(2, d.getDisjuncts().size()); |
| DisjunctionMaxQuery ndq = (DisjunctionMaxQuery) d.getDisjuncts().get(1); |
| assertEquals(0.3f, ndq.getTieBreakerMultiplier(), 0.0001f); |
| assertEquals(1, ndq.getDisjuncts().size()); |
| } |
| |
| public void testRangeQueryXML() throws ParserException, IOException { |
| Query q = parse("RangeQuery.xml"); |
| dumpResults("RangeQuery", q, 5); |
| } |
| |
| public void testUserQueryXML() throws ParserException, IOException { |
| Query q = parse("UserInputQuery.xml"); |
| dumpResults("UserInput with Filter", q, 5); |
| } |
| |
| public void testCustomFieldUserQueryXML() throws ParserException, IOException { |
| Query q = parse("UserInputQueryCustomField.xml"); |
| long h = searcher().search(q, 1000).totalHits.value; |
| assertEquals("UserInputQueryCustomField should produce 0 result ", 0, h); |
| } |
| |
| public void testBoostingTermQueryXML() throws Exception { |
| Query q = parse("BoostingTermQuery.xml"); |
| dumpResults("BoostingTermQuery", q, 5); |
| } |
| |
| public void testSpanTermXML() throws Exception { |
| Query q = parse("SpanQuery.xml"); |
| dumpResults("Span Query", q, 5); |
| SpanQuery sq = parseAsSpan("SpanQuery.xml"); |
| dumpResults("Span Query", sq, 5); |
| assertEquals(q, sq); |
| } |
| |
| public void testSpanPositionRangeQueryXML() throws Exception { |
| Query q = parse("SpanPositionRangeQuery.xml"); |
| long h = searcher().search(q, 10).totalHits.value; |
| assertEquals("SpanPositionRangeQuery should produce 2 result ", 2, h); |
| SpanQuery sq = parseAsSpan("SpanPositionRangeQuery.xml"); |
| dumpResults("SpanPositionRangeQuery", sq, 5); |
| assertEquals(q, sq); |
| } |
| |
| public void testSpanNearQueryWithoutSlopXML() throws Exception { |
| Exception expectedException = new NumberFormatException("For input string: \"\""); |
| try { |
| Query q = parse("SpanNearQueryWithoutSlop.xml"); |
| fail("got query "+q+" instead of expected exception "+expectedException); |
| } catch (Exception e) { |
| assertEquals(expectedException.toString(), e.toString()); |
| } |
| try { |
| SpanQuery sq = parseAsSpan("SpanNearQueryWithoutSlop.xml"); |
| fail("got span query "+sq+" instead of expected exception "+expectedException); |
| } catch (Exception e) { |
| assertEquals(expectedException.toString(), e.toString()); |
| } |
| } |
| |
| public void testConstantScoreQueryXML() throws Exception { |
| Query q = parse("ConstantScoreQuery.xml"); |
| dumpResults("ConstantScoreQuery", q, 5); |
| } |
| |
| public void testMatchAllDocsPlusFilterXML() throws ParserException, IOException { |
| Query q = parse("MatchAllDocsQuery.xml"); |
| dumpResults("MatchAllDocsQuery with range filter", q, 5); |
| } |
| |
| public void testNestedBooleanQuery() throws ParserException, IOException { |
| Query q = parse("NestedBooleanQuery.xml"); |
| dumpResults("Nested Boolean query", q, 5); |
| } |
| |
| public void testPointRangeQuery() throws ParserException, IOException { |
| Query q = parse("PointRangeQuery.xml"); |
| dumpResults("PointRangeQuery", q, 5); |
| } |
| |
| public void testPointRangeQueryWithoutLowerTerm() throws ParserException, IOException { |
| Query q = parse("PointRangeQueryWithoutLowerTerm.xml"); |
| dumpResults("PointRangeQueryWithoutLowerTerm", q, 5); |
| } |
| |
| public void testPointRangeQueryWithoutUpperTerm() throws ParserException, IOException { |
| Query q = parse("PointRangeQueryWithoutUpperTerm.xml"); |
| dumpResults("PointRangeQueryWithoutUpperTerm", q, 5); |
| } |
| |
| public void testPointRangeQueryWithoutRange() throws ParserException, IOException { |
| Query q = parse("PointRangeQueryWithoutRange.xml"); |
| dumpResults("PointRangeQueryWithoutRange", q, 5); |
| } |
| |
| //================= Helper methods =================================== |
| |
| protected String defaultField() { |
| return defaultField; |
| } |
| |
| protected Analyzer analyzer() { |
| if (analyzer == null) { |
| analyzer = newAnalyzer(); |
| } |
| return analyzer; |
| } |
| |
| protected CoreParser coreParser() { |
| if (coreParser == null) { |
| coreParser = newCoreParser(defaultField, analyzer()); |
| } |
| return coreParser; |
| } |
| |
| private CoreParserTestIndexData indexData() { |
| if (indexData == null) { |
| try { |
| indexData = new CoreParserTestIndexData(analyzer()); |
| } catch (Exception e) { |
| fail("caught Exception "+e); |
| } |
| } |
| return indexData; |
| } |
| |
| protected IndexReader reader() { |
| return indexData().reader; |
| } |
| |
| protected IndexSearcher searcher() { |
| return indexData().searcher; |
| } |
| |
| protected void parseShouldFail(String xmlFileName, String expectedParserExceptionMessage) throws IOException { |
| Query q = null; |
| ParserException pe = null; |
| try { |
| q = parse(xmlFileName); |
| } catch (ParserException e) { |
| pe = e; |
| } |
| assertNull("for "+xmlFileName+" unexpectedly got "+q, q); |
| assertNotNull("expected a ParserException for "+xmlFileName, pe); |
| assertEquals("expected different ParserException for "+xmlFileName, |
| expectedParserExceptionMessage, pe.getMessage()); |
| } |
| |
| protected Query parse(String xmlFileName) throws ParserException, IOException { |
| return implParse(xmlFileName, false); |
| } |
| |
| protected SpanQuery parseAsSpan(String xmlFileName) throws ParserException, IOException { |
| return (SpanQuery)implParse(xmlFileName, true); |
| } |
| |
| private Query implParse(String xmlFileName, boolean span) throws ParserException, IOException { |
| try (InputStream xmlStream = TestCoreParser.class.getResourceAsStream(xmlFileName)) { |
| assertNotNull("Test XML file " + xmlFileName + " cannot be found", xmlStream); |
| if (span) { |
| return coreParser().parseAsSpanQuery(xmlStream); |
| } else { |
| return coreParser().parse(xmlStream); |
| } |
| } |
| } |
| |
| protected Query rewrite(Query q) throws IOException { |
| return q.rewrite(reader()); |
| } |
| |
| protected void dumpResults(String qType, Query q, int numDocs) throws IOException { |
| if (VERBOSE) { |
| System.out.println("TEST: qType=" + qType + " numDocs=" + numDocs + " " + q.getClass().getCanonicalName() + " query=" + q); |
| } |
| final IndexSearcher searcher = searcher(); |
| TopDocs hits = searcher.search(q, numDocs); |
| final boolean producedResults = (hits.totalHits.value > 0); |
| if (!producedResults) { |
| System.out.println("TEST: qType=" + qType + " numDocs=" + numDocs + " " + q.getClass().getCanonicalName() + " query=" + q); |
| } |
| if (VERBOSE) { |
| ScoreDoc[] scoreDocs = hits.scoreDocs; |
| for (int i = 0; i < Math.min(numDocs, hits.totalHits.value); i++) { |
| Document ldoc = searcher.doc(scoreDocs[i].doc); |
| System.out.println("[" + ldoc.get("date") + "]" + ldoc.get("contents")); |
| } |
| System.out.println(); |
| } |
| assertTrue(qType + " produced no results", producedResults); |
| } |
| } |