/* * 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.handler.component; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.Assert; import org.apache.lucene.util.LuceneTestCase.Slow; import org.apache.lucene.util.LuceneTestCase.SuppressTempFileChecks; import org.apache.solr.BaseDistributedSearchTestCase; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SpellingParams; import org.apache.solr.common.util.NamedList; import org.junit.BeforeClass; import org.junit.Test; /** * Test for SpellCheckComponent's distributed querying * * @since solr 1.5 * * @see org.apache.solr.handler.component.SpellCheckComponent */ @Slow @SuppressTempFileChecks(bugUrl = "https://issues.apache.org/jira/browse/SOLR-1877 Spellcheck IndexReader leak bug?") public class DistributedSpellCheckComponentTest extends BaseDistributedSearchTestCase { public DistributedSpellCheckComponentTest() { //Helpful for debugging //fixShardCount=true; //shardCount=2; //stress=0; } @BeforeClass public static void beforeClass() throws Exception { useFactory(null); // need an FS factory } private void q(Object... q) throws Exception { final ModifiableSolrParams params = new ModifiableSolrParams(); for (int i = 0; i < q.length; i += 2) { params.add(q[i].toString(), q[i + 1].toString()); } controlClient.query(params); // query a random server params.set("shards", shards); int which = r.nextInt(clients.size()); SolrClient client = clients.get(which); client.query(params); } @Override public void validateControlData(QueryResponse control) throws Exception { NamedList<Object> nl = control.getResponse(); @SuppressWarnings("unchecked") NamedList<Object> sc = (NamedList<Object>) nl.get("spellcheck"); @SuppressWarnings("unchecked") NamedList<Object> sug = (NamedList<Object>) sc.get("suggestions"); if(sug.size()==0) { Assert.fail("Control data did not return any suggestions."); } } @Test public void test() throws Exception { del("*:*"); index(id, "1", "lowerfilt", "toyota"); index(id, "2", "lowerfilt", "chevrolet"); index(id, "3", "lowerfilt", "suzuki"); index(id, "4", "lowerfilt", "ford"); index(id, "5", "lowerfilt", "ferrari"); index(id, "6", "lowerfilt", "jaguar"); index(id, "7", "lowerfilt", "mclaren"); index(id, "8", "lowerfilt", "sonata"); index(id, "9", "lowerfilt", "The quick red fox jumped over the lazy brown dogs."); index(id, "10", "lowerfilt", "blue"); index(id, "12", "lowerfilt", "glue"); index(id, "13", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "14", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "15", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "16", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "17", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "18", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "19", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "20", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "21", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "22", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "23", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "24", "lowerfilt", "The quote red fox jumped over the lazy brown dogs."); index(id, "25", "lowerfilt", "The quicker red fox jumped over the lazy brown dogs."); index(id, "26", "lowerfilt", "rod fix"); commit(); handle.clear(); handle.put("timestamp", SKIPVAL); handle.put("maxScore", SKIPVAL); // we care only about the spellcheck results handle.put("response", SKIP); handle.put("grouped", SKIP); //Randomly select either IndexBasedSpellChecker or DirectSolrSpellChecker String requestHandlerName = "spellCheckCompRH_Direct"; String reqHandlerWithWordbreak = "spellCheckWithWordbreak_Direct"; if(random().nextBoolean()) { requestHandlerName = "spellCheckCompRH"; reqHandlerWithWordbreak = "spellCheckWithWordbreak"; } //Shortcut names String build = SpellingParams.SPELLCHECK_BUILD; String extended = SpellingParams.SPELLCHECK_EXTENDED_RESULTS; String count = SpellingParams.SPELLCHECK_COUNT; String collate = SpellingParams.SPELLCHECK_COLLATE; String collateExtended = SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS; String maxCollationTries = SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES; String maxCollations = SpellingParams.SPELLCHECK_MAX_COLLATIONS; String altTermCount = SpellingParams.SPELLCHECK_ALTERNATIVE_TERM_COUNT; String maxResults = SpellingParams.SPELLCHECK_MAX_RESULTS_FOR_SUGGEST; //Build the dictionary for IndexBasedSpellChecker q(buildRequest("*:*", false, "spellCheckCompRH", false, build, "true")); //Test Basic Functionality query(buildRequest("toyata", true, requestHandlerName, random().nextBoolean(), (String[]) null)); query(buildRequest("toyata", true, requestHandlerName, random().nextBoolean(), extended, "true")); query(buildRequest("bluo", true, requestHandlerName, random().nextBoolean(), extended, "true", count, "4")); //Test Collate functionality query(buildRequest("The quick reb fox jumped over the lazy brown dogs", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "4", collate, "true")); query(buildRequest("lowerfilt:(+quock +reb)", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "10", maxCollations, "10", collateExtended, "true")); query(buildRequest("lowerfilt:(+quock +reb)", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "10", maxCollations, "10", collateExtended, "false")); query(buildRequest("lowerfilt:(+quock +reb)", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "0", maxCollations, "1", collateExtended, "false")); //Test context-sensitive collate query(buildRequest("lowerfilt:(\"quick red fox\")", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "10", maxCollations, "1", collateExtended, "false", altTermCount, "5", maxResults, "10")); query(buildRequest("lowerfilt:(\"rod fix\")", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "10", maxCollations, "1", collateExtended, "false", altTermCount, "5", maxResults, "10")); query(buildRequest("lowerfilt:(\"rod fix\")", false, requestHandlerName, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "10", maxCollations, "1", collateExtended, "false", altTermCount, "5", maxResults, ".10", "fq", "id:[13 TO 22]")); //Test word-break spellchecker query(buildRequest("lowerfilt:(+quock +redfox +jum +ped)", false, reqHandlerWithWordbreak, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "0", maxCollations, "1", collateExtended, "true")); query(buildRequest("lowerfilt:(+rodfix)", false, reqHandlerWithWordbreak, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "0", maxCollations, "1", collateExtended, "true")); query(buildRequest("lowerfilt:(+son +ata)", false, reqHandlerWithWordbreak, random().nextBoolean(), extended, "true", count, "10", collate, "true", maxCollationTries, "0", maxCollations, "1", collateExtended, "true")); } private Object[] buildRequest(String q, boolean useSpellcheckQ, String handlerName, boolean useGrouping, String... addlParams) { List<Object> params = new ArrayList<>(); params.add("q"); params.add(useSpellcheckQ ? "*:*" : q); if(useSpellcheckQ) { params.add("spellcheck.q"); params.add(q); } params.add("fl"); params.add("id,lowerfilt"); params.add("qt"); params.add(handlerName); params.add("shards.qt"); params.add(handlerName); params.add("spellcheck"); params.add("true"); if(useGrouping) { params.add("group"); params.add("true"); params.add("group.field"); params.add("id"); } if(addlParams!=null) { params.addAll(Arrays.asList(addlParams)); } return params.toArray(new Object[params.size()]); } }