Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,57 +20,27 @@
import java.lang.invoke.MethodHandles;
import org.apache.lucene.tests.util.QuickPatchThreadsFilter;
import org.apache.solr.SolrIgnoredThreadsFilter;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;

@ThreadLeakFilters(filters = {SolrIgnoredThreadsFilter.class, QuickPatchThreadsFilter.class})
public class ExtractingRequestHandlerTikaServerTest extends ExtractingRequestHandlerTestAbstract {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

public static GenericContainer<?> tika;
@ClassRule
public static final TikaServerContainerRule tikaContainer = new TikaServerContainerRule();

@BeforeClass
@SuppressWarnings("resource")
public static void beforeClassTika() {
Assume.assumeFalse(
"Skipping on s390x", "s390x".equalsIgnoreCase(System.getProperty("os.arch")));

String baseUrl;
try {
tika =
new GenericContainer<>("apache/tika:3.2.3.0-full")
.withExposedPorts(9998)
.waitingFor(Wait.forListeningPort());
tika.start();
baseUrl = "http://" + tika.getHost() + ":" + tika.getMappedPort(9998);
System.setProperty("solr.test.tikaserver.url", baseUrl);
System.setProperty("solr.test.extraction.backend", "tikaserver");
System.setProperty("solr.test.tikaserver.metadata.compatibility", "true");
log.info("Using extraction backend 'tikaserver'. Tika server running on {}", baseUrl);
initCore("solrconfig.xml", "schema.xml", getFile("extraction/solr"));
} catch (Throwable t) {
// Skip tests if Docker/Testcontainers are not available in the environment
Assume.assumeNoException("Docker/Testcontainers not available; skipping test", t);
}
}

@AfterClass
public static void afterClassTika() {
if (tika != null) {
try {
tika.stop();
} catch (Throwable t) {
// ignore
} finally {
tika = null;
}
}
public static void beforeClassTika() throws Exception {
String baseUrl = tikaContainer.getBaseUrl();
System.setProperty("solr.test.tikaserver.url", baseUrl);
System.setProperty("solr.test.extraction.backend", "tikaserver");
System.setProperty("solr.test.tikaserver.metadata.compatibility", "true");
log.info("Using extraction backend 'tikaserver'. Tika server running on {}", baseUrl);
initCore("solrconfig.xml", "schema.xml", getFile("extraction/solr"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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.handler.extraction;

import java.lang.invoke.MethodHandles;
import org.junit.Assume;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;

/**
* JUnit rule that manages a single Apache Tika Server Testcontainer. Declare as a
* {@code @ClassRule} so the (expensive to start) server is shared across all {@code @Test} methods
* in a class instead of being restarted for each one; JUnit starts it before, and stops it after,
* the whole class runs.
*
* <p>Skips the calling test (via {@link Assume}) instead of failing outright if
* Docker/Testcontainers isn't available in this environment.
*/
public class TikaServerContainerRule extends ExternalResource {

private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

public static final String TIKA_DOCKER_IMAGE = "apache/tika:3.2.3.0-full";

private GenericContainer<?> tika;
private String baseUrl;

@Override
@SuppressWarnings("resource")
protected void before() {
Assume.assumeFalse(
"Skipping on s390x", "s390x".equalsIgnoreCase(System.getProperty("os.arch")));
Assume.assumeTrue(
"Docker/Testcontainers not available; skipping test",
DockerClientFactory.instance().isDockerAvailable());

tika =
new GenericContainer<>(TIKA_DOCKER_IMAGE)
.withExposedPorts(9998)
.waitingFor(Wait.forListeningPort());
tika.start();
baseUrl = "http://" + tika.getHost() + ":" + tika.getMappedPort(9998);
}

@Override
protected void after() {
if (tika != null) {
try {
tika.stop();
} catch (Exception e) {
log.error("Exception stopping Tika container", e);
} finally {
tika = null;
}
}
}

public String getBaseUrl() {
return baseUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.apache.solr.handler.extraction.fromtika.ToXMLContentHandler;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.testcontainers.containers.GenericContainer;

/**
* Integration tests for TikaServerExtractionBackend using a real Tika Server via Testcontainers.
Expand All @@ -60,35 +57,8 @@ public boolean reject(Thread t) {
}
}

private static GenericContainer<?> tika;
private static String baseUrl;

@SuppressWarnings("resource")
@BeforeClass
public static void startTikaServer() {
Assume.assumeFalse(
"Skipping on s390x", "s390x".equalsIgnoreCase(System.getProperty("os.arch")));

try {
tika = new GenericContainer<>("apache/tika:3.2.3.0-full").withExposedPorts(9998);
tika.start();
baseUrl = "http://" + tika.getHost() + ":" + tika.getMappedPort(9998);
} catch (Throwable t) {
// Skip tests if Docker/Testcontainers are not available in the environment
Assume.assumeNoException("Docker/Testcontainers not available; skipping TikaServer tests", t);
}
}

@AfterClass
public static void stopTikaServer() {
if (tika != null) {
try {
tika.stop();
} catch (Throwable ignore) {
}
tika = null;
}
}
@ClassRule
public static final TikaServerContainerRule tikaContainer = new TikaServerContainerRule();

private static ExtractionRequest newRequest(
String resourceName,
Expand All @@ -109,8 +79,8 @@ private static ExtractionRequest newRequest(

@Test
public void testExtractTextAndMetadata() throws Exception {
Assume.assumeTrue("Tika server container not started", tika != null);
try (TikaServerExtractionBackend backend = new TikaServerExtractionBackend(baseUrl)) {
try (TikaServerExtractionBackend backend =
new TikaServerExtractionBackend(tikaContainer.getBaseUrl())) {
byte[] data = "Hello TestContainers".getBytes(StandardCharsets.UTF_8);
try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
ExtractionResult res = backend.extract(in, newRequest("test.txt", "text/plain", "text"));
Expand All @@ -129,8 +99,8 @@ public void testExtractTextAndMetadata() throws Exception {

@Test
public void testExtractWithSaxHandlerXml() throws Exception {
Assume.assumeTrue("Tika server container not started", tika != null);
try (TikaServerExtractionBackend backend = new TikaServerExtractionBackend(baseUrl)) {
try (TikaServerExtractionBackend backend =
new TikaServerExtractionBackend(tikaContainer.getBaseUrl())) {
byte[] data = "Hello XML".getBytes(StandardCharsets.UTF_8);
ExtractionRequest request = newRequest("test.txt", "text/plain", "xml");
try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
Expand All @@ -151,8 +121,8 @@ public void testExtractWithSaxHandlerXml() throws Exception {

@Test
public void testPdfWithImageRecursive() throws Exception {
Assume.assumeTrue("Tika server container not started", tika != null);
try (TikaServerExtractionBackend backend = new TikaServerExtractionBackend(baseUrl)) {
try (TikaServerExtractionBackend backend =
new TikaServerExtractionBackend(tikaContainer.getBaseUrl())) {
byte[] data = Files.readAllBytes(getFile("extraction/pdf-with-image.pdf"));
// Enable recursive extraction and set header to extract images from PDF
ExtractionRequest request =
Expand Down Expand Up @@ -182,11 +152,10 @@ private ExtractionRequest newRequest(String file, String contentType, String con

@Test
public void testMaxCharsLimitEnforced() throws Exception {
Assume.assumeTrue("Tika server container not started", tika != null);
// Set a very small max chars limit and attempt to extract more than that
long maxChars = 10L;
try (TikaServerExtractionBackend backend =
new TikaServerExtractionBackend(baseUrl, 180, null, maxChars)) {
new TikaServerExtractionBackend(tikaContainer.getBaseUrl(), 180, null, maxChars)) {
byte[] data =
("This content is definitely longer than ten characters.")
.getBytes(StandardCharsets.UTF_8);
Expand All @@ -205,10 +174,9 @@ public void testMaxCharsLimitEnforced() throws Exception {

@Test
public void testMaxCharsLimitEnforcedWithSaxHandler() throws Exception {
Assume.assumeTrue("Tika server container not started", tika != null);
long maxChars = 10L;
try (TikaServerExtractionBackend backend =
new TikaServerExtractionBackend(baseUrl, 180, null, maxChars)) {
new TikaServerExtractionBackend(tikaContainer.getBaseUrl(), 180, null, maxChars)) {
byte[] data =
("This content is definitely longer than ten characters.")
.getBytes(StandardCharsets.UTF_8);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class AbstractS3ClientTest extends SolrTestCaseJ4 {
protected static final String BUCKET_NAME = "test-bucket";

@ClassRule
public static final S3MockContainerRule S3_MOCK_RULE = new S3MockContainerRule(BUCKET_NAME);
public static final S3MockContainerRule s3MockContainer = new S3MockContainerRule(BUCKET_NAME);

S3StorageClient client;
private SocketProxy proxy;
Expand All @@ -58,7 +58,7 @@ public void setUpClient() throws Exception {

// We are using a proxy in front of S3Mock to be able to test connection loss
proxy = new SocketProxy();
proxy.open(URI.create(S3_MOCK_RULE.getHttpEndpoint()));
proxy.open(URI.create(s3MockContainer.getHttpEndpoint()));
client =
new S3StorageClient(
BUCKET_NAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class S3BackupRepositoryTest extends AbstractBackupRepositoryTest {
public Path temporaryFolder;

@ClassRule
public static final S3MockContainerRule S3_MOCK_RULE = new S3MockContainerRule(BUCKET_NAME);
public static final S3MockContainerRule s3MockContainer = new S3MockContainerRule(BUCKET_NAME);

@Before
@Override
Expand Down Expand Up @@ -338,18 +338,18 @@ protected NamedList<Object> getBaseBackupRepositoryConfiguration() {
NamedList<Object> args = new NamedList<>();
args.add(S3BackupRepositoryConfig.REGION, Region.US_EAST_1.id());
args.add(S3BackupRepositoryConfig.BUCKET_NAME, BUCKET_NAME);
args.add(S3BackupRepositoryConfig.ENDPOINT, S3_MOCK_RULE.getHttpEndpoint());
args.add(S3BackupRepositoryConfig.ENDPOINT, s3MockContainer.getHttpEndpoint());
return args;
}

private void pushObject(String path, String content) {
try (S3Client s3 = S3_MOCK_RULE.createS3ClientV2()) {
try (S3Client s3 = s3MockContainer.createS3ClientV2()) {
s3.putObject(b -> b.bucket(BUCKET_NAME).key(path), RequestBody.fromString(content));
}
}

private Path pullObject(String path) throws IOException {
try (S3Client s3 = S3_MOCK_RULE.createS3ClientV2()) {
try (S3Client s3 = s3MockContainer.createS3ClientV2()) {
Path file = Files.createTempFile(temporaryFolder, "junit", null);
InputStream input =
s3.getObject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class S3IncrementalBackupTest extends AbstractIncrementalBackupTest {
private static final String BUCKET_NAME = S3IncrementalBackupTest.class.getSimpleName();

@ClassRule
public static final S3MockContainerRule S3_MOCK_RULE = new S3MockContainerRule(BUCKET_NAME);
public static final S3MockContainerRule s3MockContainer = new S3MockContainerRule(BUCKET_NAME);

public static final String SOLR_XML =
"<solr>\n"
Expand Down Expand Up @@ -134,7 +134,7 @@ public static void setupClass() throws Exception {
.replace("BAD_BUCKET", BUCKET_NAME)
.replace("BUCKET", BUCKET_NAME)
.replace("REGION", Region.US_EAST_1.id())
.replace("ENDPOINT", S3_MOCK_RULE.getHttpEndpoint()))
.replace("ENDPOINT", s3MockContainer.getHttpEndpoint()))
.configure();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class S3InstallShardTest extends AbstractInstallShardTest {
AbstractInstallShardTest.defaultSolrXmlTextWithBackupRepository(BACKUP_REPOSITORY_XML);

@ClassRule
public static final S3MockContainerRule S3_MOCK_RULE = new S3MockContainerRule(BUCKET_NAME);
public static final S3MockContainerRule s3MockContainer = new S3MockContainerRule(BUCKET_NAME);

@BeforeClass
public static void setupClass() throws Exception {
Expand All @@ -82,7 +82,7 @@ public static void setupClass() throws Exception {
SOLR_XML
.replace("BUCKET", BUCKET_NAME)
.replace("REGION", Region.US_EAST_1.id())
.replace("ENDPOINT", S3_MOCK_RULE.getHttpEndpoint()))
.replace("ENDPOINT", s3MockContainer.getHttpEndpoint()))
.configure();

bootstrapBackupRepositoryData("/");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
Expand Down Expand Up @@ -55,14 +56,13 @@ public S3MockContainerRule(String bucketName) {

@Override
protected void before() {
Assume.assumeTrue(
"Docker/Testcontainers not available; skipping test",
DockerClientFactory.instance().isDockerAvailable());
s3MockContainer =
new S3MockContainer(DockerImageName.parse(S3MOCK_DOCKER_IMAGE))
.withInitialBuckets(bucketName);
try {
s3MockContainer.start();
} catch (Throwable t) {
Assume.assumeNoException("Docker/Testcontainers not available; skipping test", t);
}
s3MockContainer.start();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ public class S3OutputStreamTest extends SolrTestCaseJ4 {

private static final String BUCKET = S3OutputStreamTest.class.getSimpleName();

@ClassRule public static final S3MockContainerRule S3_MOCK_RULE = new S3MockContainerRule(BUCKET);
@ClassRule
public static final S3MockContainerRule s3MockContainer = new S3MockContainerRule(BUCKET);

private S3Client s3;

@Before
public void setUpClient() {
s3 = S3_MOCK_RULE.createS3ClientV2();
s3 = s3MockContainer.createS3ClientV2();
}

@After
Expand Down
Loading