SOLR-14901: TestPackages uses binary precompiled classes to refer to analysis factory FQCNs

This commit is contained in:
noble 2020-09-29 15:25:22 +10:00
parent 98a49ed18d
commit 01da67c728
5 changed files with 201 additions and 74 deletions

View File

@ -0,0 +1,29 @@
/*
* 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 my.pkg;
import java.util.Map;
import org.apache.solr.pkg.TestPackages;
public class MyPatternReplaceCharFilterFactory extends TestPackages.BasePatternReplaceCharFilterFactory {
public MyPatternReplaceCharFilterFactory(Map<String, String> args) {
super(args);
}
}

View File

@ -0,0 +1,23 @@
/*
* 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 my.pkg;
import org.apache.solr.schema.TextField;
public class MyTextField extends TextField {
}

View File

@ -0,0 +1,28 @@
/*
* 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 my.pkg;
import java.util.Map;
import org.apache.solr.pkg.TestPackages;
public class MyWhitespaceTokenizerFactory extends TestPackages.BaseWhitespaceTokenizerFactory {
public MyWhitespaceTokenizerFactory(Map<String, String> args) {
super(args);
}
}

View File

@ -17,6 +17,7 @@
package org.apache.solr.pkg; package org.apache.solr.pkg;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
@ -24,9 +25,12 @@ import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.analysis.core.WhitespaceTokenizerFactory;
import org.apache.lucene.analysis.pattern.PatternReplaceCharFilterFactory;
import org.apache.lucene.util.ResourceLoader; import org.apache.lucene.util.ResourceLoader;
import org.apache.lucene.util.ResourceLoaderAware; import org.apache.lucene.util.ResourceLoaderAware;
import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrClient;
@ -64,6 +68,7 @@ import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.QParser; import org.apache.solr.search.QParser;
import org.apache.solr.search.QParserPlugin; import org.apache.solr.search.QParserPlugin;
import org.apache.solr.util.LogLevel; import org.apache.solr.util.LogLevel;
import org.apache.solr.util.SimplePostTool;
import org.apache.solr.util.plugin.SolrCoreAware; import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.data.Stat;
import org.junit.After; import org.junit.After;
@ -77,11 +82,8 @@ import static org.apache.solr.core.TestSolrConfigHandler.getFileContent;
import static org.apache.solr.filestore.TestDistribPackageStore.checkAllNodesForFile; import static org.apache.solr.filestore.TestDistribPackageStore.checkAllNodesForFile;
import static org.apache.solr.filestore.TestDistribPackageStore.readFile; import static org.apache.solr.filestore.TestDistribPackageStore.readFile;
import static org.apache.solr.filestore.TestDistribPackageStore.uploadKey; import static org.apache.solr.filestore.TestDistribPackageStore.uploadKey;
import static org.hamcrest.CoreMatchers.containsString;
@LogLevel("org.apache.solr.pkg.PackageLoader=DEBUG;org.apache.solr.pkg.PackageAPI=DEBUG") @LogLevel("org.apache.solr.pkg.PackageLoader=DEBUG;org.apache.solr.pkg.PackageAPI=DEBUG")
//@org.apache.lucene.util.LuceneTestCase.AwaitsFix(bugUrl="https://issues.apache.org/jira/browse/SOLR-13822") // leaks files
@LuceneTestCase.AwaitsFix(bugUrl="https://issues.apache.org/jira/browse/SOLR-14901")
public class TestPackages extends SolrCloudTestCase { public class TestPackages extends SolrCloudTestCase {
@Before @Before
@ -187,23 +189,23 @@ public class TestPackages extends SolrCloudTestCase {
.build(); .build();
cluster.getSolrClient().request(v2r); cluster.getSolrClient().request(v2r);
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "1.0" ); "mypkg", "1.0" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "1.0" ); "mypkg", "1.0" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "1.0" ); "mypkg", "1.0" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "updateProcessor", "myurp", COLLECTION_NAME, "updateProcessor", "myurp",
"mypkg", "1.0" ); "mypkg", "1.0" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "expressible", "mincopy", COLLECTION_NAME, "expressible", "mincopy",
"mypkg", "1.0" ); "mypkg", "1.0" );
@ -253,19 +255,19 @@ public class TestPackages extends SolrCloudTestCase {
add.files = Arrays.asList(new String[]{FILE2,URP2, EXPR1}); add.files = Arrays.asList(new String[]{FILE2,URP2, EXPR1});
req.process(cluster.getSolrClient()); req.process(cluster.getSolrClient());
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "updateProcessor", "myurp", COLLECTION_NAME, "updateProcessor", "myurp",
"mypkg", "1.1" ); "mypkg", "1.1" );
@ -284,15 +286,15 @@ public class TestPackages extends SolrCloudTestCase {
req.process(cluster.getSolrClient()); req.process(cluster.getSolrClient());
//now let's verify that the classes are updated //now let's verify that the classes are updated
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "2.1" ); "mypkg", "2.1" );
@ -323,15 +325,15 @@ public class TestPackages extends SolrCloudTestCase {
.build(); .build();
delete.process(cluster.getSolrClient()); delete.process(cluster.getSolrClient());
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "2.1" ); "mypkg", "2.1" );
@ -339,15 +341,15 @@ public class TestPackages extends SolrCloudTestCase {
delVersion.version = "2.1"; delVersion.version = "2.1";
delete.process(cluster.getSolrClient()); delete.process(cluster.getSolrClient());
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "1.1" ); "mypkg", "1.1" );
@ -368,15 +370,15 @@ public class TestPackages extends SolrCloudTestCase {
//the collections mypkg is set to use version 1.1 //the collections mypkg is set to use version 1.1
//so no upgrade //so no upgrade
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "1.1" ); "mypkg", "1.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "1.1" ); "mypkg", "1.1" );
@ -398,15 +400,15 @@ public class TestPackages extends SolrCloudTestCase {
.process(cluster.getSolrClient()); .process(cluster.getSolrClient());
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "queryResponseWriter", "json1", COLLECTION_NAME, "queryResponseWriter", "json1",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "searchComponent", "get", COLLECTION_NAME, "searchComponent", "get",
"mypkg", "2.1" ); "mypkg", "2.1" );
verifyCmponent(cluster.getSolrClient(), verifyComponent(cluster.getSolrClient(),
COLLECTION_NAME, "requestHandler", "/runtime", COLLECTION_NAME, "requestHandler", "/runtime",
"mypkg", "2.1" ); "mypkg", "2.1" );
@ -445,11 +447,8 @@ public class TestPackages extends SolrCloudTestCase {
cluster.shutdown(); cluster.shutdown();
} }
} }
@SuppressWarnings({"unchecked","rawtypes"})
@SuppressWarnings({"unchecked"}) private void executeReq(String uri, JettySolrRunner jetty, Utils.InputStreamConsumer parser, Map expected) throws Exception {
private void executeReq(String uri, JettySolrRunner jetty,
@SuppressWarnings({"rawtypes"})Utils.InputStreamConsumer parser,
@SuppressWarnings({"rawtypes"})Map expected) throws Exception {
try(HttpSolrClient client = (HttpSolrClient) jetty.newClient()){ try(HttpSolrClient client = (HttpSolrClient) jetty.newClient()){
TestDistribPackageStore.assertResponseValues(10, TestDistribPackageStore.assertResponseValues(10,
() -> { () -> {
@ -463,7 +462,7 @@ public class TestPackages extends SolrCloudTestCase {
} }
} }
private void verifyCmponent(SolrClient client, String COLLECTION_NAME, private void verifyComponent(SolrClient client, String COLLECTION_NAME,
String componentType, String componentName, String pkg, String version) throws Exception { String componentType, String componentName, String pkg, String version) throws Exception {
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
SolrParams params = new MapSolrParams((Map) Utils.makeMap("collection", COLLECTION_NAME, SolrParams params = new MapSolrParams((Map) Utils.makeMap("collection", COLLECTION_NAME,
@ -644,7 +643,6 @@ public class TestPackages extends SolrCloudTestCase {
} }
} }
@SuppressWarnings("rawtypes")
public void testSchemaPlugins() throws Exception { public void testSchemaPlugins() throws Exception {
String COLLECTION_NAME = "testSchemaLoadingColl"; String COLLECTION_NAME = "testSchemaLoadingColl";
System.setProperty("managed.schema.mutable", "true"); System.setProperty("managed.schema.mutable", "true");
@ -659,7 +657,7 @@ public class TestPackages extends SolrCloudTestCase {
byte[] derFile = readFile("cryptokeys/pub_key512.der"); byte[] derFile = readFile("cryptokeys/pub_key512.der");
uploadKey(derFile, PackageStoreAPI.KEYS_DIR+"/pub_key512.der", cluster); uploadKey(derFile, PackageStoreAPI.KEYS_DIR+"/pub_key512.der", cluster);
postFileAndWait(cluster, "runtimecode/schema-plugins.jar.bin", FILE1, postFileAndWait(cluster, "runtimecode/schema-plugins.jar.bin", FILE1,
"iSRhrogDyt9P1htmSf/krh1kx9oty3TYyWm4GKHQGlb8a+X4tKCe9kKk+3tGs+bU9zq5JBZ5txNXsn96aZem5A=="); "U+AdO/jgY3DtMpeFRGoTQk72iA5g/qjPvdQYPGBaXB5+ggcTZk4FoIWiueB0bwGJ8Mg3V/elxOqEbD2JR8R0tA==");
String FILE2 = "/schemapkg/payload-component.jar"; String FILE2 = "/schemapkg/payload-component.jar";
postFileAndWait(cluster, "runtimecode/payload-component.jar.bin", FILE2, postFileAndWait(cluster, "runtimecode/payload-component.jar.bin", FILE2,
@ -698,7 +696,7 @@ public class TestPackages extends SolrCloudTestCase {
add = new Package.AddVersion(); add = new Package.AddVersion();
add.version = "2.0"; add.version = "2.0";
add.pkg = "schemapkg"; add.pkg = "schemapkg";
add.files = Arrays.asList(new String[]{FILE1}); add.files = Arrays.asList(FILE1);
req = new V2Request.Builder("/cluster/package") req = new V2Request.Builder("/cluster/package")
.forceV2(true) .forceV2(true)
.withMethod(SolrRequest.METHOD.POST) .withMethod(SolrRequest.METHOD.POST)
@ -759,7 +757,56 @@ public class TestPackages extends SolrCloudTestCase {
fail("should have failed with message : " + expectErrorMsg); fail("should have failed with message : " + expectErrorMsg);
} catch (BaseHttpSolrClient.RemoteExecutionException e) { } catch (BaseHttpSolrClient.RemoteExecutionException e) {
String msg = e.getMetaData()._getStr(errPath, ""); String msg = e.getMetaData()._getStr(errPath, "");
assertThat(msg, containsString(expectErrorMsg)); assertTrue("should have failed with message: " + expectErrorMsg + "actual message : " + msg,
msg.contains(expectErrorMsg)
);
} }
} }
public static class BasePatternReplaceCharFilterFactory extends PatternReplaceCharFilterFactory {
public BasePatternReplaceCharFilterFactory(Map<String, String> args) {
super(args);
}
}
public static class BaseWhitespaceTokenizerFactory extends WhitespaceTokenizerFactory {
public BaseWhitespaceTokenizerFactory(Map<String, String> args) {
super(args);
}
}
/*
//copy the jav files to a package and then run the main method
public static void main(String[] args) throws Exception {
persistZip("/tmp/x.jar", MyPatternReplaceCharFilterFactory.class, MyTextField.class, MyWhitespaceTokenizerFactory.class);
}*/
public static ByteBuffer persistZip(String loc,
@SuppressWarnings({"rawtypes"}) Class... classes) throws IOException {
ByteBuffer jar = generateZip(classes);
try (FileOutputStream fos = new FileOutputStream(loc)) {
fos.write(jar.array(), 0, jar.limit());
fos.flush();
}
return jar;
}
public static ByteBuffer generateZip(@SuppressWarnings({"rawtypes"}) Class... classes) throws IOException {
SimplePostTool.BAOS bos = new SimplePostTool.BAOS();
try (ZipOutputStream zipOut = new ZipOutputStream(bos)) {
zipOut.setLevel(ZipOutputStream.DEFLATED);
for (@SuppressWarnings({"rawtypes"}) Class c : classes) {
String path = c.getName().replace('.', '/').concat(".class");
ZipEntry entry = new ZipEntry(path);
ByteBuffer b = SimplePostTool.inputStreamToByteArray(c.getClassLoader().getResourceAsStream(path));
zipOut.putNextEntry(entry);
zipOut.write(b.array(), 0, b.limit());
zipOut.closeEntry();
}
}
return bos.getByteBuffer();
}
} }