blob: 213e22480d59c05e737b0bd8686ab5a28e331096 [file] [log] [blame]
/*
* 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 static org.hamcrest.CoreMatchers.containsString;
import java.io.IOException;
import java.util.List;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.TermsResponse;
import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.apache.solr.cloud.ConfigRequest;
import org.apache.solr.cloud.MiniSolrCloudCluster;
import org.apache.solr.common.util.NamedList;
import org.junit.Test;
public class CustomTermsComponentTest extends ShardsWhitelistTest {
public static class CustomTermsComponent extends TermsComponent {
public void init( @SuppressWarnings({"rawtypes"})NamedList args )
{
super.init(args);
}
@Override
protected void checkShardsWhitelist(final ResponseBuilder rb, final List<String> lst) {
// ignore shards whitelist
}
}
private static String addCustomHandlerWithTermsComponentConfig(final MiniSolrCloudCluster cluster, final String collection,
final String defaultHandlerName, final String shardsWhitelist) throws Exception {
return addCustomHandler(cluster, collection, defaultHandlerName, shardsWhitelist);
}
private static String addCustomHandlerWithCustomTermsComponent(final MiniSolrCloudCluster cluster, final String collection,
final String defaultHandlerName) throws Exception {
return addCustomHandler(cluster, collection, defaultHandlerName, null);
}
private static String addCustomHandler(final MiniSolrCloudCluster cluster, final String collection,
final String defaultHandlerName, final String shardsWhitelist) throws Exception {
// determine custom handler name (the exact name should not matter)
final String customHandlerName = defaultHandlerName+"_custom"+random().nextInt();
// determine custom terms component name (the exact name should not matter)
final String customTermsComponentName = TermsComponent.COMPONENT_NAME+"_custom"+random().nextInt();
// determine terms component class name and attributes
final String customTermsComponentClass;
final String customTermsComponentAttributesJSON;
if (shardsWhitelist != null) {
customTermsComponentClass = TermsComponent.class.getName();
customTermsComponentAttributesJSON =
" '"+HttpShardHandlerFactory.INIT_SHARDS_WHITELIST+"' : '"+shardsWhitelist+"',\n";
} else {
customTermsComponentClass = CustomTermsComponent.class.getName();
customTermsComponentAttributesJSON = "";
}
// add custom component
cluster.getSolrClient().request(
new ConfigRequest(
"{\n" +
" 'add-searchcomponent': {\n" +
customTermsComponentAttributesJSON +
" 'name': '"+customTermsComponentName+"',\n" +
" 'class': '"+customTermsComponentClass+"'\n" +
" }\n" +
"}"),
collection);
// add custom handler
cluster.getSolrClient().request(
new ConfigRequest(
"{\n" +
" 'add-requesthandler': {\n" +
" 'name' : '"+customHandlerName+"',\n" +
" 'class' : '"+SearchHandler.class.getName()+"',\n" +
" 'components' : [ '"+QueryComponent.COMPONENT_NAME+"', '"+customTermsComponentName+"' ]\n" +
" }\n" +
"}"),
collection);
return customHandlerName;
}
@Test
@Override
public void test() throws Exception {
for (final String clusterId : clusterId2cluster.keySet()) {
final MiniSolrCloudCluster cluster = clusterId2cluster.get(clusterId);
final String collection = COLLECTION_NAME;
doTest(cluster, collection);
}
}
private static void doTest(final MiniSolrCloudCluster cluster, final String collection) throws Exception {
// add some documents
final String id = "id";
final String f1 = "a_t";
final String f2 = "b_t";
final String v1 = "bee";
final String v2 = "buzz";
{
new UpdateRequest()
.add(sdoc(id, 1, f1, v1, f2, v2+" "+v2+" "+v2))
.add(sdoc(id, 2, f1, v1+" "+v1, f2, v2+" "+v2))
.add(sdoc(id, 3, f1, v1+" "+v1+" "+v1, f2, v2))
.commit(cluster.getSolrClient(), collection);
}
// search for the documents' terms ...
final String defaultHandlerName = "/select";
// search with the default handler ...
final String shards = findAndCheckTerms(cluster, collection,
defaultHandlerName,
null, // ... without specifying shards
(random().nextBoolean() ? null : f1), v1,
(random().nextBoolean() ? null : f2), v2,
null);
// search with the default handler ...
findAndCheckTerms(cluster, collection,
defaultHandlerName,
shards, // ... with specified shards, but all valid
(random().nextBoolean() ? null : f1), v1,
(random().nextBoolean() ? null : f2), v2,
null);
ignoreException("not on the shards whitelist");
// this case should fail
findAndCheckTerms(cluster, collection,
defaultHandlerName,
shards + ",http://" + DEAD_HOST_1, // ... with specified shards with one invalid
(random().nextBoolean() ? null : f1), v1,
(random().nextBoolean() ? null : f2), v2,
"No live SolrServers available to handle this request");
unIgnoreException("not on the shards whitelist");
// configure a custom handler ...
final String customHandlerName;
if (random().nextBoolean()) {
// ... with a shards whitelist
customHandlerName = addCustomHandlerWithTermsComponentConfig(cluster, collection, defaultHandlerName, shards);
} else {
// ... with a custom terms component that disregards shards whitelist logic
customHandlerName = addCustomHandlerWithCustomTermsComponent(cluster, collection, defaultHandlerName);
}
// search with the custom handler ...
findAndCheckTerms(cluster, collection,
customHandlerName,
shards, // ... with specified shards
(random().nextBoolean() ? null : f1), v1,
(random().nextBoolean() ? null : f2), v2,
null);
}
private static String findAndCheckTerms(final MiniSolrCloudCluster cluster, final String collection,
String requestHandlerName, String in_shards,
String field1, String value1,
String field2, String value2,
String solrServerExceptionMessagePrefix) throws IOException {
// compose the query ...
final SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.setRequestHandler(requestHandlerName);
solrQuery.add("shards.qt", requestHandlerName);
// ... asking for terms ...
solrQuery.setTerms(true);
if (field1 != null) {
solrQuery.addTermsField(field1);
}
if (field2 != null) {
solrQuery.addTermsField(field2);
}
// ... and shards info ...
solrQuery.add("shards.info", "true");
// ... passing shards to use (if we have a preference)
if (in_shards != null) {
solrQuery.add("shards", in_shards);
}
// make the query
final QueryResponse queryResponse;
try {
queryResponse = new QueryRequest(solrQuery)
.process(cluster.getSolrClient(), collection);
assertNull("expected exception ("+solrServerExceptionMessagePrefix+") not encountered", solrServerExceptionMessagePrefix);
} catch (SolrServerException sse) {
assertNotNull("unexpectedly caught exception "+sse, solrServerExceptionMessagePrefix);
assertTrue(sse.getMessage().startsWith(solrServerExceptionMessagePrefix));
assertThat(sse.getCause().getMessage(), containsString("not on the shards whitelist"));
return null;
}
// analyse the response ...
final TermsResponse termsResponse = queryResponse.getTermsResponse();
// ... checking the terms returned ...
checkTermsResponse(termsResponse, field1, value1);
checkTermsResponse(termsResponse, field2, value2);
// ... and assemble info about the shards ...
final String out_shards = extractShardAddresses(queryResponse, ",");
// ... to return to the caller
return out_shards;
}
@SuppressWarnings("unchecked")
private static String extractShardAddresses(final QueryResponse queryResponse, final String delimiter) {
final StringBuilder sb = new StringBuilder();
final NamedList<Object> nl = (NamedList<Object>)queryResponse.getResponse().get("shards.info");
assertNotNull(queryResponse.toString(), nl);
for (int ii = 0; ii < nl.size(); ++ii) {
final String shardAddress = (String)((NamedList<Object>)nl.getVal(ii)).get("shardAddress");
if (sb.length() > 0) {
sb.append(delimiter);
}
sb.append(shardAddress);
}
return sb.toString();
}
private static void checkTermsResponse(TermsResponse termsResponse, String field, String value) {
if (field != null) {
final List<Term> ttList = termsResponse.getTerms(field);
assertEquals(1, ttList.size());
assertEquals(value, ttList.get(0).getTerm());
}
}
}