/* * 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 org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.core.SolrCore; import org.junit.Assume; import org.junit.BeforeClass; import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import java.util.ArrayList; import java.util.List; /** * Tests {@link StatelessScriptUpdateProcessorFactory}. * * TODO: This test, to run from an IDE, requires a working directory of <path-to>/solr/core/src/test-files. Fix! */ public class StatelessScriptUpdateProcessorFactoryTest extends UpdateProcessorTestBase { @BeforeClass public static void beforeClass() throws Exception { Assume.assumeNotNull((new ScriptEngineManager()).getEngineByExtension("js")); initCore("solrconfig-script-updateprocessor.xml", "schema12.xml"); } /** * simple test of a basic script processor chain using the full * RequestHandler + UpdateProcessorChain flow */ public void testFullRequestHandlerFlow() throws Exception { assertU("Simple assertion that adding a document works", adoc("id", "4055", "subject", "Hoss")); assertU(commit()); assertQ("couldn't find hoss using script added field", req("q","script_added_i:[40 TO 45]", "fq","id:4055") ,"//result[@numFound=1]" ,"//str[@name='id'][.='4055']" ); // clean up processDeleteById("run-no-scripts","4055"); processCommit("run-no-scripts"); } public void testSingleScript() throws Exception { SolrCore core = h.getCore(); UpdateRequestProcessorChain chained = core.getUpdateProcessingChain("single-script"); final StatelessScriptUpdateProcessorFactory factory = ((StatelessScriptUpdateProcessorFactory) chained.getProcessors().get(0)); final List<String> functionMessages = new ArrayList<>(); factory.setScriptEngineCustomizer(new ScriptEngineCustomizer() { @Override public void customize(ScriptEngine engine) { engine.put("functionMessages", functionMessages); } }); assertNotNull(chained); SolrInputDocument d = processAdd("single-script", doc(f("id", "1"), f("name", " foo "), f("subject", "bar"))); processCommit("run-no-scripts"); assertQ("couldn't find doc by id", req("q","id:1") , "//result[@numFound=1]"); processDeleteById("single-script","1"); processCommit("single-script"); assertQ("found deleted doc", req("q","id:1") , "//result[@numFound=0]"); assertEquals(3, functionMessages.size()); assertTrue(functionMessages.contains("processAdd0")); assertTrue(functionMessages.contains("processDelete0")); assertTrue(functionMessages.contains("processCommit0")); } public void testMultipleScripts() throws Exception { SolrCore core = h.getCore(); for (final String chain : new String[] {"dual-scripts-arr", "dual-scripts-strs"}) { UpdateRequestProcessorChain chained = core.getUpdateProcessingChain(chain); final StatelessScriptUpdateProcessorFactory factory = ((StatelessScriptUpdateProcessorFactory) chained.getProcessors().get(0)); final List<String> functionMessages = new ArrayList<>(); ScriptEngineCustomizer customizer = new ScriptEngineCustomizer() { @Override public void customize(ScriptEngine engine) { engine.put("functionMessages", functionMessages); } }; factory.setScriptEngineCustomizer(customizer); assertNotNull(chained); SolrInputDocument d = processAdd(chain, doc(f("id", "2"), f("name", " foo "), f("subject", "bar"))); assertEquals(chain + " didn't add Double field", 42.3d, d.getFieldValue("script_added_d")); assertEquals(chain + " didn't add integer field", new Integer(42), d.getFieldValue("script_added_i")); processCommit("run-no-scripts"); assertQ(chain + ": couldn't find doc by id", req("q","id:2") , "//result[@numFound=1]"); processDeleteById(chain, "2"); processCommit(chain); assertEquals(chain, 6, functionMessages.size()); assertTrue(chain, functionMessages.contains("processAdd0")); assertTrue(chain, functionMessages.contains("processAdd1")); assertTrue(chain + ": script order doesn't match conf order", functionMessages.indexOf("processAdd0") < functionMessages.indexOf("processAdd1")); assertTrue(chain, functionMessages.contains("processDelete0")); assertTrue(chain, functionMessages.contains("processDelete1")); assertTrue(chain + ": script order doesn't match conf order", functionMessages.indexOf("processDelete0") < functionMessages.indexOf("processDelete1")); assertTrue(chain, functionMessages.contains("processCommit0")); assertTrue(chain, functionMessages.contains("processCommit1")); assertTrue(chain + ": script order doesn't match conf order", functionMessages.indexOf("processCommit0") < functionMessages.indexOf("processCommit1")); finish(chain); assertEquals(chain, 8, functionMessages.size()); assertTrue(chain, functionMessages.contains("finish0")); assertTrue(chain, functionMessages.contains("finish1")); assertTrue(chain + ": script order doesn't match conf order", functionMessages.indexOf("finish0") < functionMessages.indexOf("finish1")); assertQ(chain + ": found deleted doc", req("q","id:2") , "//result[@numFound=0]"); } } public void testConditionalExecution() throws Exception { for (String chain : new String[] {"conditional-script", "conditional-scripts"}) { ModifiableSolrParams reqParams = new ModifiableSolrParams(); SolrInputDocument d = processAdd(chain, reqParams, doc(f("id", "3"), f("name", " foo "), f("subject", "bar"))); assertFalse(chain + " added String field despite condition", d.containsKey("script_added_s")); assertFalse(chain + " added Double field despite condition", d.containsKey("script_added_d")); reqParams.add("go-for-it", "true"); d = processAdd(chain, reqParams, doc(f("id", "4"), f("name", " foo "), f("subject", "bar"))); assertEquals(chain + " didn't add String field", "i went for it", d.getFieldValue("script_added_s")); assertEquals(chain +" didn't add Double field", 42.3d, d.getFieldValue("script_added_d")); assertEquals(chain + " didn't add integer field", new Integer(42), d.getFieldValue("script_added_i")); } } public void testForceEngine() throws Exception { Assume.assumeNotNull((new ScriptEngineManager()).getEngineByName("javascript")); final String chain = "force-script-engine"; SolrInputDocument d = processAdd(chain, doc(f("id", "5"), f("name", " foo "), f("subject", "bar"))); assertEquals(chain +" didn't add Double field", 42.3d, d.getFieldValue("script_added_d")); assertEquals(chain + " didn't add integer field", new Integer(42), d.getFieldValue("script_added_i")); } public void testPropogatedException() throws Exception { final String chain = "error-on-add"; try { SolrInputDocument d = processAdd(chain, doc(f("id", "5"), f("name", " foo "), f("subject", "bar"))); } catch (SolrException e) { assertTrue("Exception doesn't contain script error string: " + e.getMessage(), 0 < e.getMessage().indexOf("no-soup-fo-you")); return; } fail("Did not get exception from script"); } public void testMissingFunctions() throws Exception { final String chain = "missing-functions"; try { SolrInputDocument d = processAdd(chain, doc(f("id", "5"), f("name", " foo "), f("subject", "bar"))); } catch (SolrException e) { assertTrue("Exception doesn't contain expected error: " + e.getMessage(), 0 < e.getMessage().indexOf("processAdd")); return; } fail("Did not get exception from script"); } public void testJavaScriptCompatibility() throws Exception { final String chain = "javascript-compatibility"; SolrInputDocument d = processAdd(chain, doc(f("id", "5"), f("name", " foo "), f("subject", "BAR"))); assertEquals("bar", d.getFieldValue("term_s")); } }