blob: fbb42103ed74b6708ab3f0a0cb1e48bf68222cef [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.search;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.SolrTestCase;
import org.junit.Test;
/**
* Check standard query parsers for class loading problems during initialization (NAME field is final and static).
* Because every query plugin extend {@link org.apache.solr.search.QParserPlugin} and contains own instance of {@link org.apache.solr.search.QParserPlugin#standardPlugins},
* There are a cyclic dependencies of static fields between plugins and order of initialization can be wrong if NAME field is not final.
* This leads to NPEs during Solr startup.
* @see <a href="https://issues.apache.org/jira/browse/SOLR-5526">SOLR-5526</a>
* @see org.apache.solr.search.QParserPlugin#standardPlugins
*
*/
public class TestStandardQParsers extends SolrTestCase {
/**
* Field name of constant mandatory for query parser plugin.
*/
public static final String FIELD_NAME = "NAME";
/**
* Test standard query parsers registered in {@link org.apache.solr.search.QParserPlugin#standardPlugins}
* have NAME field which is final, static, and matches the registered name.
*/
@Test
public void testRegisteredName() throws Exception {
List<String> notStatic = new ArrayList<>(QParserPlugin.standardPlugins.size());
List<String> notFinal = new ArrayList<>(QParserPlugin.standardPlugins.size());
List<String> mismatch = new ArrayList<>(QParserPlugin.standardPlugins.size());
for (Map.Entry<String, QParserPlugin> pair : QParserPlugin.standardPlugins.entrySet()) {
String regName = pair.getKey();
Class<? extends QParserPlugin> clazz = pair.getValue().getClass();;
Field nameField = clazz.getField(FIELD_NAME);
int modifiers = nameField.getModifiers();
if (!Modifier.isFinal(modifiers)) {
notFinal.add(clazz.getName());
}
if (!Modifier.isStatic(modifiers)) {
notStatic.add(clazz.getName());
} else if (! regName.equals(nameField.get(null))) {
mismatch.add(regName +" != "+ nameField.get(null) +"("+ clazz.getName() +")");
}
}
assertTrue("All standard QParsers must have final NAME, broken: " + notFinal,
notFinal.isEmpty());
assertTrue("All standard QParsers must have static NAME, broken: " + notStatic,
notStatic.isEmpty());
assertTrue("All standard QParsers must be registered using NAME, broken: " + mismatch,
mismatch.isEmpty());
assertTrue("DEFAULT_QTYPE is not in the standard set of registered names: " +
QParserPlugin.DEFAULT_QTYPE,
QParserPlugin.standardPlugins.keySet().contains(QParserPlugin.DEFAULT_QTYPE));
}
/**
* Test that "lucene" is the default query parser.
*/
@Test
public void testDefaultQType() throws Exception {
assertEquals(LuceneQParserPlugin.NAME, QParserPlugin.DEFAULT_QTYPE);
assertEquals("lucene", LuceneQParserPlugin.NAME);
}
}