blob: 43667540d3c2c100f52bb5b3232afb0fb97a04e5 [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.update.processor;
import static org.apache.solr.update.processor.DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.core.SolrCore;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.SolrTestCaseJ4;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class UpdateRequestProcessorFactoryTest extends SolrTestCaseJ4 {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@BeforeClass
public static void beforeClass() throws Exception {
System.setProperty("enable.runtime.lib", "true");
initCore("solrconfig-transformers.xml", "schema.xml");
}
public void testRequestTimeUrp(){
SolrCore core = h.getCore();
ModifiableSolrParams params = new ModifiableSolrParams()
.add("processor", "template")
.add("template.field", "id_t:{firstName}_{lastName}")
.add("template.field", "another_t:{lastName}_{firstName}")
.add("template.field", "missing_t:{lastName}_{unKnown}");
UpdateRequestProcessorChain chain = core.getUpdateProcessorChain(params);
List<UpdateRequestProcessorFactory> l = chain.getProcessors();
assertTrue(l.get(0) instanceof TemplateUpdateProcessorFactory);
}
public void testConfiguration() throws Exception
{
SolrCore core = h.getCore();
// make sure it loaded the factories
UpdateRequestProcessorChain chained = core.getUpdateProcessingChain( "standard" );
// Make sure it got 3 items (4 configured, 1 is enable=false)
assertEquals("wrong number of (enabled) factories in chain",
3, chained.getProcessors().size() );
// first one should be log, and it should be configured properly
UpdateRequestProcessorFactory first = chained.getProcessors().get(0);
assertEquals("wrong factory at front of chain",
LogUpdateProcessorFactory.class, first.getClass());
LogUpdateProcessorFactory log = (LogUpdateProcessorFactory)first;
assertEquals("wrong config for LogUpdateProcessorFactory.maxNumToLog",
100, log.maxNumToLog );
assertEquals("wrong config for LogUpdateProcessorFactory.slowUpdateThresholdMillis",
2000, log.slowUpdateThresholdMillis);
UpdateRequestProcessorChain custom = core.getUpdateProcessingChain( null );
CustomUpdateRequestProcessorFactory link = (CustomUpdateRequestProcessorFactory) custom.getProcessors().get(0);
assertEquals( custom, core.getUpdateProcessingChain( "" ) );
assertEquals( custom, core.getUpdateProcessingChain( "custom" ) );
// Make sure the NamedListArgs got through ok
assertEquals( "{name={n8=88,n9=99}}", link.args.toString() );
}
public void testUpdateDistribChainSkipping() throws Exception {
// a key part of this test is verifying that LogUpdateProcessor is found in all chains because it
// is a @RunAlways processor -- but in order for that to work, we have to sanity check that the log
// level is at least "INFO" otherwise the factory won't even produce a processor and all our assertions
// are for nought. (see LogUpdateProcessorFactory.getInstance)
//
// TODO: maybe create a new mock Processor w/ @RunAlways annot if folks feel requiring INFO is evil.
assertTrue("Tests must be run with INFO level logging "+
"otherwise LogUpdateProcessor isn't used and can't be tested.", log.isInfoEnabled());
final int EXPECTED_CHAIN_LENGTH = 5;
SolrCore core = h.getCore();
for (final String name : Arrays.asList("distrib-chain-explicit",
"distrib-chain-implicit",
"distrib-chain-noop")) {
UpdateRequestProcessor proc;
List<UpdateRequestProcessor> procs;
UpdateRequestProcessorChain chain = core.getUpdateProcessingChain(name);
assertNotNull(name, chain);
// either explicitly, or because of injection
assertEquals(name + " factory chain length: " + chain.toString(), EXPECTED_CHAIN_LENGTH,
chain.getProcessors().size());
// test a basic (non distrib) chain
proc = chain.createProcessor(req(), new SolrQueryResponse());
procs = procToList(proc);
int expectedProcLen = EXPECTED_CHAIN_LENGTH;
if ("distrib-chain-noop".equals(name)) { // NoOpDistributingUpdateProcessorFactory produces no processor
expectedProcLen--;
}
if (procs.stream().anyMatch(p -> p.getClass().getSimpleName().equals("NestedUpdateProcessor"))) {
expectedProcLen++; // NestedUpdate sneaks in via RunUpdate's Factory.
}
assertEquals(name + " procs size: " + procs.toString(), expectedProcLen, procs.size());
// Custom comes first in all three of our chains
assertTrue(name + " first processor isn't a CustomUpdateRequestProcessor: " + procs.toString(),
( // compare them both just because i'm going insane and the more checks the better
proc instanceof CustomUpdateRequestProcessor
&& procs.get(0) instanceof CustomUpdateRequestProcessor));
// Log should always come second in our chain.
assertNotNull(name + " proc.next is null", proc.next);
assertNotNull(name + " second proc is null", procs.get(1));
assertTrue(name + " second proc isn't LogUpdateProcessor: " + procs.toString(),
( // compare them both just because i'm going insane and the more checks the better
proc.next instanceof LogUpdateProcessorFactory.LogUpdateProcessor
&& procs.get(1) instanceof LogUpdateProcessorFactory.LogUpdateProcessor));
// fetch the distributed version of this chain
proc = chain.createProcessor(req(DISTRIB_UPDATE_PARAM, "NONE"), // just some non-blank value
new SolrQueryResponse());
procs = procToList(proc);
assertNotNull(name + " (distrib) chain produced null proc", proc);
assertFalse(name + " (distrib) procs is empty", procs.isEmpty());
// for these 3 (distrib) chains, the first proc should always be LogUpdateProcessor
assertTrue(name + " (distrib) first proc should be LogUpdateProcessor because of @RunAlways: "
+ procs.toString(),
( // compare them both just because i'm going insane and the more checks the better
proc instanceof LogUpdateProcessorFactory.LogUpdateProcessor
&& procs.get(0) instanceof LogUpdateProcessorFactory.LogUpdateProcessor));
// for these 3 (distrib) chains, the last proc should always be RunUpdateProcessor
assertTrue(name + " (distrib) last processor isn't a RunUpdateProcessor: " + procs.toString(),
procs.get(procs.size()-1) instanceof RunUpdateProcessorFactory.RunUpdateProcessor );
// either 1 proc was droped in distrib mode, or 1 for the "implicit" chain
expectedProcLen = EXPECTED_CHAIN_LENGTH;
expectedProcLen--; // -1 = all chains lose CustomUpdateRequestProcessorFactory
if ("distrib-chain-explicit".equals(name) == false) {
// -1 = distrib-chain-noop: NoOpDistributingUpdateProcessorFactory produces no processor
// -1 = distrib-chain-implicit: does RemoveBlank before distrib
expectedProcLen--;
}
if (procs.stream().anyMatch(p -> p.getClass().getSimpleName().equals("NestedUpdateProcessor"))) {
expectedProcLen++; // NestedUpdate sneaks in via RunUpdate's Factory.
}
assertEquals(name + " (distrib) chain has wrong length: " + procs.toString(),
expectedProcLen, procs.size());
}
}
/**
* walks the "next" values of the proc building up a List of the procs for easier testing
*/
public static List<UpdateRequestProcessor> procToList(UpdateRequestProcessor proc) {
List<UpdateRequestProcessor> result = new ArrayList<>(7);
while (null != proc) {
result.add(proc);
proc = proc.next;
}
return result;
}
}