/* * eXist Open Source Native XML Database * Copyright (C) 2001-2017 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.exist.indexing.range; import org.apache.logging.log4j.Logger; import org.easymock.Capture; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.xml.soap.Node; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import static junit.framework.TestCase.assertTrue; import static org.easymock.EasyMock.*; import static org.exist.indexing.lucene.LuceneIndexConfig.MATCH_ATTR; import static org.exist.indexing.lucene.LuceneIndexConfig.QNAME_ATTR; public class RangeIndexConfigTest { /** * @see https://github.com/eXist-db/exist/issues/1339 */ @Test public void errorsHaveSourceContext() throws NoSuchFieldException, IllegalAccessException { final String badCreateQName = "tei:persName "; // Note the trailing final String mockCollectionXConfUri = "/db/system/conf/db/mock/collection.xconf"; final NodeList mockConfigNodes = createMock(NodeList.class); final Element mockConfigNode = createMock(Element.class); final NodeList mockCreates = createMock(NodeList.class); final Document mockCreateDocument = createMock(Document.class); final Element mockCreate = createMock(Element.class); final NodeList mockEmptyNodeList = createMock(NodeList.class); final Logger mockLogger = createMock(Logger.class); expect(mockConfigNodes.getLength()).andReturn(1).times(2); expect(mockConfigNodes.item(0)).andReturn(mockConfigNode); expect(mockConfigNode.getNodeType()).andReturn(Node.ELEMENT_NODE); expect(mockConfigNode.getLocalName()).andReturn(RangeIndexConfig.CONFIG_ROOT); expect(mockConfigNode.getChildNodes()).andReturn(mockCreates); expect(mockCreates.getLength()).andReturn(1).times(2); expect(mockCreates.item(0)).andReturn(mockCreate); expect(mockCreate.getNodeType()).andReturn(Node.ELEMENT_NODE); expect(mockCreate.getLocalName()).andReturn(RangeIndexConfig.CREATE_ELEM); // skip getFieldsAndConditions expect(mockCreate.getChildNodes()).andReturn(mockEmptyNodeList); expect(mockEmptyNodeList.getLength()).andReturn(0); expect(mockCreate.getAttribute(MATCH_ATTR)).andReturn(null); expect(mockCreate.hasAttribute(QNAME_ATTR)).andReturn(true); expect(mockCreate.getAttribute(QNAME_ATTR)).andReturn(badCreateQName); expect(mockCreate.getOwnerDocument()).andReturn(mockCreateDocument); expect(mockCreateDocument.getDocumentURI()).andReturn(mockCollectionXConfUri); final Capture<String> errorMsgCapture = newCapture(); mockLogger.error(capture(errorMsgCapture)); replay(mockConfigNodes, mockConfigNode, mockCreates, mockCreateDocument, mockCreate, mockEmptyNodeList, mockLogger); final Map<String, String> namespaces = new HashMap<>(); namespaces.put("tei", "http://www.tei-c.org/ns/1.0"); overrideLogger(RangeIndexConfig.class, mockLogger); final RangeIndexConfig config = new RangeIndexConfig(mockConfigNodes, namespaces); assertTrue(errorMsgCapture.getValue().contains("'" + badCreateQName + "' not a valid local name")); assertTrue(errorMsgCapture.getValue().contains("(" + mockCollectionXConfUri + ")")); verify(mockConfigNodes, mockConfigNode, mockCreates, mockCreateDocument, mockCreate, mockEmptyNodeList, mockLogger); } private void overrideLogger(final Class clazz, final Logger logger) throws NoSuchFieldException, IllegalAccessException { final Field loggerField = clazz.getDeclaredField("LOG"); // allow access to private field loggerField.setAccessible(true); // remove final modifier final Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(loggerField, loggerField.getModifiers() & ~Modifier.FINAL); loggerField.set(null, logger); } }