| /* |
| * 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.core; |
| |
| import org.apache.commons.io.FileUtils; |
| import org.apache.lucene.util.IOUtils; |
| import org.apache.solr.SolrTestCaseJ4; |
| import org.apache.solr.common.SolrException; |
| import org.junit.After; |
| import org.xml.sax.SAXParseException; |
| |
| import java.io.File; |
| import java.util.Collection; |
| import java.util.Map; |
| import java.util.regex.Pattern; |
| |
| public class CoreContainerCoreInitFailuresTest extends SolrTestCaseJ4 { |
| |
| File solrHome = null; |
| CoreContainer cc = null; |
| |
| private void init(final String dirSuffix) { |
| // would be nice to do this in an @Before method, |
| // but junit doesn't let @Before methods have test names |
| solrHome = new File(TEMP_DIR, this.getClass().getName() + "_" + dirSuffix); |
| assertTrue("Failed to mkdirs solrhome [" + solrHome + "]", solrHome.mkdirs()); |
| } |
| |
| @After |
| public void cleanUp() throws Exception { |
| if (cc != null) { |
| cc.shutdown(); |
| cc = null; |
| } |
| |
| if (null != solrHome) { |
| if (solrHome.exists()) { |
| FileUtils.deleteDirectory(solrHome); |
| } |
| solrHome = null; |
| } |
| } |
| |
| public void testFlowWithEmpty() throws Exception { |
| // reused state |
| Map<String,Exception> failures = null; |
| Collection<String> cores = null; |
| Exception fail = null; |
| |
| init("empty_flow"); |
| |
| // solr.xml |
| File solrXml = new File(solrHome, "solr.xml"); |
| FileUtils.write(solrXml, EMPTY_SOLR_XML, IOUtils.CHARSET_UTF_8.toString()); |
| |
| // ---- |
| // init the CoreContainer |
| cc = new CoreContainer(solrHome.getAbsolutePath()); |
| cc.load(); |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 0, cores.size()); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 0, failures.size()); |
| |
| // ----- |
| // try to add a collection with a path that doesn't exist |
| final CoreDescriptor bogus = new CoreDescriptor(cc, "bogus", "bogus_path"); |
| try { |
| ignoreException(Pattern.quote("bogus_path")); |
| cc.create(bogus); |
| fail("bogus inst dir failed to trigger exception from create"); |
| } catch (SolrException e) { |
| assertTrue("init exception doesn't mention bogus dir: " + e.getCause().getCause().getMessage(), |
| 0 < e.getCause().getCause().getMessage().indexOf("bogus_path")); |
| |
| } |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 0, cores.size()); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 1, failures.size()); |
| fail = failures.get("bogus"); |
| assertNotNull("null failure for test core", fail); |
| assertTrue("init failure doesn't mention problem: " + fail.getCause().getMessage(), |
| 0 < fail.getCause().getMessage().indexOf("bogus_path")); |
| |
| // check that we get null accessing a non-existent core |
| assertNull(cc.getCore("does_not_exist")); |
| // check that we get a 500 accessing the core with an init failure |
| try { |
| SolrCore c = cc.getCore("bogus"); |
| fail("Failed to get Exception on accessing core with init failure"); |
| } catch (SolrException ex) { |
| assertEquals(500, ex.code()); |
| // double wrapped |
| String cause = ex.getCause().getCause().getMessage(); |
| assertTrue("getCore() ex cause doesn't mention init fail: " + cause, |
| 0 < cause.indexOf("bogus_path")); |
| |
| } |
| |
| // let the test end here, with some recorded failures, and let cleanUp() |
| // verify that there is no problem shuting down CoreContainer with known |
| // SolrCore failures |
| } |
| |
| public void testFlowBadFromStart() throws Exception { |
| |
| // reused state |
| Map<String,Exception> failures = null; |
| Collection<String> cores = null; |
| Exception fail = null; |
| |
| init("bad_flow"); |
| |
| // start with two collections: one valid, and one broken |
| File solrXml = new File(solrHome, "solr.xml"); |
| FileUtils.write(solrXml, BAD_SOLR_XML, IOUtils.CHARSET_UTF_8.toString()); |
| |
| // our "ok" collection |
| FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"), |
| FileUtils.getFile(solrHome, "col_ok", "conf", "solrconfig.xml")); |
| FileUtils.copyFile(getFile("solr/collection1/conf/schema-minimal.xml"), |
| FileUtils.getFile(solrHome, "col_ok", "conf", "schema.xml")); |
| |
| // our "bad" collection |
| ignoreException(Pattern.quote("DummyMergePolicy")); |
| FileUtils.copyFile(getFile("solr/collection1/conf/bad-mp-solrconfig.xml"), |
| FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml")); |
| FileUtils.copyFile(getFile("solr/collection1/conf/schema-minimal.xml"), |
| FileUtils.getFile(solrHome, "col_bad", "conf", "schema.xml")); |
| |
| |
| // ----- |
| // init the CoreContainer with the mix of ok/bad cores |
| cc = new CoreContainer(solrHome.getAbsolutePath()); |
| cc.load(); |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 1, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 1, failures.size()); |
| fail = failures.get("col_bad"); |
| assertNotNull("null failure for test core", fail); |
| assertTrue("init failure doesn't mention problem: " + fail.getMessage(), |
| 0 < fail.getMessage().indexOf("DummyMergePolicy")); |
| |
| // check that we get null accessing a non-existent core |
| assertNull(cc.getCore("does_not_exist")); |
| // check that we get a 500 accessing the core with an init failure |
| try { |
| SolrCore c = cc.getCore("col_bad"); |
| fail("Failed to get Exception on accessing core with init failure"); |
| } catch (SolrException ex) { |
| assertEquals(500, ex.code()); |
| // double wrapped |
| String cause = ex.getCause().getCause().getMessage(); |
| assertTrue("getCore() ex cause doesn't mention init fail: " + cause, |
| 0 < cause.indexOf("DummyMergePolicy")); |
| } |
| |
| // ----- |
| // "fix" the bad collection |
| FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"), |
| FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml")); |
| final CoreDescriptor fixed = new CoreDescriptor(cc, "col_bad", "col_bad"); |
| cc.register("col_bad", cc.create(fixed), false); |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 2, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| assertTrue("col_bad not found", cores.contains("col_bad")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 0, failures.size()); |
| |
| |
| // ----- |
| // try to add a collection with a path that doesn't exist |
| final CoreDescriptor bogus = new CoreDescriptor(cc, "bogus", "bogus_path"); |
| try { |
| ignoreException(Pattern.quote("bogus_path")); |
| cc.create(bogus); |
| fail("bogus inst dir failed to trigger exception from create"); |
| } catch (SolrException e) { |
| assertTrue("init exception doesn't mention bogus dir: " + e.getCause().getCause().getMessage(), |
| 0 < e.getCause().getCause().getMessage().indexOf("bogus_path")); |
| |
| } |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 2, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| assertTrue("col_bad not found", cores.contains("col_bad")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 1, failures.size()); |
| fail = failures.get("bogus"); |
| assertNotNull("null failure for test core", fail); |
| assertTrue("init failure doesn't mention problem: " + fail.getCause().getMessage(), |
| 0 < fail.getCause().getMessage().indexOf("bogus_path")); |
| |
| // check that we get null accessing a non-existent core |
| assertNull(cc.getCore("does_not_exist")); |
| // check that we get a 500 accessing the core with an init failure |
| try { |
| SolrCore c = cc.getCore("bogus"); |
| fail("Failed to get Exception on accessing core with init failure"); |
| } catch (SolrException ex) { |
| assertEquals(500, ex.code()); |
| // double wrapped |
| String cause = ex.getCause().getCause().getMessage(); |
| assertTrue("getCore() ex cause doesn't mention init fail: " + cause, |
| 0 < cause.indexOf("bogus_path")); |
| } |
| |
| // ----- |
| // register bogus as an alias for col_ok and confirm failure goes away |
| cc.register("bogus", cc.getCore("col_ok"), false); |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 3, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| assertTrue("col_bad not found", cores.contains("col_bad")); |
| assertTrue("bogus not found", cores.contains("bogus")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 0, failures.size()); |
| |
| |
| // ----- |
| // break col_bad's config and try to RELOAD to add failure |
| |
| final long col_bad_old_start = getCoreStartTime(cc, "col_bad"); |
| |
| FileUtils.write |
| (FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml"), |
| "This is giberish, not valid XML <", |
| IOUtils.CHARSET_UTF_8.toString()); |
| |
| try { |
| ignoreException(Pattern.quote("SAX")); |
| cc.reload("col_bad"); |
| fail("corrupt solrconfig.xml failed to trigger exception from reload"); |
| } catch (SolrException e) { |
| assertTrue("We're supposed to have a wrapped SAXParserException here, but we don't", |
| e.getCause().getCause() instanceof SAXParseException); |
| SAXParseException se = (SAXParseException)e.getCause().getCause(); |
| assertTrue("reload exception doesn't refer to slrconfig.xml " + se.getSystemId(), |
| 0 < se.getSystemId().indexOf("solrconfig.xml")); |
| |
| } |
| |
| assertEquals("Failed core reload should not have changed start time", |
| col_bad_old_start, getCoreStartTime(cc, "col_bad")); |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 3, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| assertTrue("col_bad not found", cores.contains("col_bad")); |
| assertTrue("bogus not found", cores.contains("bogus")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 1, failures.size()); |
| fail = failures.get("col_bad"); |
| assertNotNull("null failure for test core", fail); |
| assertTrue("init failure isn't SAXParseException", |
| fail.getCause() instanceof SAXParseException); |
| assertTrue("init failure doesn't mention problem: " + fail.toString(), |
| 0 < ((SAXParseException)fail.getCause()).getSystemId().indexOf("solrconfig.xml")); |
| |
| // ---- |
| // fix col_bad's config (again) and RELOAD to fix failure |
| FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-defaults.xml"), |
| FileUtils.getFile(solrHome, "col_bad", "conf", "solrconfig.xml")); |
| cc.reload("col_bad"); |
| |
| assertTrue("Core reload should have changed start time", |
| col_bad_old_start < getCoreStartTime(cc, "col_bad")); |
| |
| |
| // check that we have the cores we expect |
| cores = cc.getCoreNames(); |
| assertNotNull("core names is null", cores); |
| assertEquals("wrong number of cores", 3, cores.size()); |
| assertTrue("col_ok not found", cores.contains("col_ok")); |
| assertTrue("col_bad not found", cores.contains("col_bad")); |
| assertTrue("bogus not found", cores.contains("bogus")); |
| |
| // check that we have the failures we expect |
| failures = cc.getCoreInitFailures(); |
| assertNotNull("core failures is a null map", failures); |
| assertEquals("wrong number of core failures", 0, failures.size()); |
| |
| } |
| |
| private final long getCoreStartTime(final CoreContainer cc, |
| final String name) { |
| SolrCore tmp = cc.getCore(name); |
| try { |
| return tmp.getStartTime(); |
| } finally { |
| tmp.close(); |
| } |
| } |
| |
| private static final String EMPTY_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + |
| "<solr persistent=\"false\">\n" + |
| " <cores adminPath=\"/admin/cores\">\n" + |
| " </cores>\n" + |
| "</solr>"; |
| |
| private static final String BAD_SOLR_XML = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + |
| "<solr persistent=\"false\">\n" + |
| " <cores adminPath=\"/admin/cores\">\n" + |
| " <core name=\"col_ok\" instanceDir=\"col_ok\" />\n" + |
| " <core name=\"col_bad\" instanceDir=\"col_bad\" />\n" + |
| " </cores>\n" + |
| "</solr>"; |
| |
| } |