This is an automated email from the ASF dual-hosted git repository. tallison pushed a commit to branch tika-server-simplify-tests in repository https://gitbox.apache.org/repos/asf/tika.git
commit 28d6f4a13d41d068e8fc2eadf80665629fa2e4c1 Author: tallison <[email protected]> AuthorDate: Sat Jan 31 15:56:26 2026 -0500 stream line tika-server tests --- .../org/apache/tika/server/core/CXFTestBase.java | 13 ++-- .../apache/tika/server/core/TestPortAllocator.java | 46 ++++++++++++ .../org/apache/tika/server/core/TikaPipesTest.java | 83 +++++++++++----------- .../apache/tika/server/standard/TikaPipesTest.java | 72 ++++++++++--------- 4 files changed, 137 insertions(+), 77 deletions(-) diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java index 63e0044baa..c5f5d124c1 100644 --- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java +++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java @@ -51,8 +51,9 @@ import org.apache.cxf.jaxrs.JAXRSBindingFactory; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.transport.common.gzip.GZIPInInterceptor; import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,6 +68,7 @@ import org.apache.tika.server.core.resource.PipesParsingHelper; import org.apache.tika.server.core.resource.TikaResource; import org.apache.tika.server.core.resource.UnpackerResource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public abstract class CXFTestBase { private static final Logger LOG = LoggerFactory.getLogger(CXFTestBase.class); @@ -95,7 +97,8 @@ public abstract class CXFTestBase { private static final String TEMPLATE_RESOURCE = "/configs/cxf-test-base-template.json"; private static final ObjectMapper MAPPER = new ObjectMapper(); - protected static final String endPoint = "http://localhost:" + TikaServerConfig.DEFAULT_PORT; + protected final int testPort = TestPortAllocator.findFreePort(); + protected final String endPoint = "http://localhost:" + testPort; protected final static int DIGESTER_READ_LIMIT = 20 * 1024 * 1024; protected Server server; protected TikaLoader tika; @@ -178,7 +181,7 @@ public abstract class CXFTestBase { return new AverageColor((double) totalRed / (double) pixels, (double) totalGreen / (double) pixels, (double) totalBlue / (double) pixels); } - @BeforeEach + @BeforeAll public void setUp() throws Exception { Path tmp = Files.createTempFile("tika-server-test-", ".json"); try { @@ -347,7 +350,7 @@ public abstract class CXFTestBase { */ protected abstract void setUpProviders(JAXRSServerFactoryBean sf); - @AfterEach + @AfterAll public void tearDown() throws Exception { server.stop(); server.destroy(); diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TestPortAllocator.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TestPortAllocator.java new file mode 100644 index 0000000000..fcade0d292 --- /dev/null +++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TestPortAllocator.java @@ -0,0 +1,46 @@ +/* + * 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.tika.server.core; + +import java.io.IOException; +import java.net.ServerSocket; + +/** + * Allocates ephemeral ports for tests to avoid conflicts when running + * multiple builds simultaneously. + */ +public final class TestPortAllocator { + + private TestPortAllocator() { + } + + /** + * Finds and returns an available port. + * <p> + * Note: There is a small race window between closing the ServerSocket + * and the test actually binding to the port. In practice, this is + * rarely an issue since ephemeral ports are drawn from a large pool. + */ + public static int findFreePort() { + try (ServerSocket socket = new ServerSocket(0)) { + socket.setReuseAddress(true); + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Could not find free port", e); + } + } +} diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java index 08fc4a4512..38b1ec47a7 100644 --- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java +++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java @@ -44,10 +44,10 @@ import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.apache.tika.exception.TikaConfigException; import org.apache.tika.metadata.Metadata; @@ -68,76 +68,79 @@ import org.apache.tika.server.core.writer.JSONObjWriter; * This offers basic integration tests with fetchers and emitters. * We use file system fetchers and emitters. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TikaPipesTest extends CXFTestBase { private static final String PIPES_PATH = "/pipes"; - private static Path TMP_DIR; - private static Path TMP_OUTPUT_DIR; - private static Path TMP_OUTPUT_FILE; - private static Path TIKA_PIPES_LOG4j2_PATH; - private static Path TMP_NPE_OUTPUT_FILE; - private static Path TIKA_CONFIG_PATH; - private static String HELLO_WORLD = "hello_world.xml"; - private static String HELLO_WORLD_JSON = "hello_world.xml.json"; - private static String NPE_JSON = "null_pointer.xml.json"; - - private static String[] VALUE_ARRAY = new String[]{"my-value-1", "my-value-2", "my-value-3"}; + private Path tmpDir; + private Path tmpOutputDir; + private Path tmpOutputFile; + private Path tikaPipesLog4j2Path; + private Path tmpNpeOutputFile; + private Path tikaConfigPath; + private static final String HELLO_WORLD = "hello_world.xml"; + private static final String HELLO_WORLD_JSON = "hello_world.xml.json"; + private static final String NPE_JSON = "null_pointer.xml.json"; + + private static final String[] VALUE_ARRAY = new String[]{"my-value-1", "my-value-2", "my-value-3"}; private PipesResource pipesResource; + @Override @BeforeAll - public static void setUpBeforeClass() throws Exception { - TMP_DIR = Files.createTempDirectory("tika-pipes-test-"); - Path inputDir = TMP_DIR.resolve("input"); - TMP_OUTPUT_DIR = TMP_DIR.resolve("output"); - TMP_OUTPUT_FILE = TMP_OUTPUT_DIR.resolve(HELLO_WORLD_JSON); - TMP_NPE_OUTPUT_FILE = TMP_OUTPUT_DIR.resolve("null_pointer.xml.json"); + public void setUp() throws Exception { + // Initialize test directories and config before parent setup + tmpDir = Files.createTempDirectory("tika-pipes-test-"); + Path inputDir = tmpDir.resolve("input"); + tmpOutputDir = tmpDir.resolve("output"); + tmpOutputFile = tmpOutputDir.resolve(HELLO_WORLD_JSON); + tmpNpeOutputFile = tmpOutputDir.resolve("null_pointer.xml.json"); Files.createDirectories(inputDir); - Files.createDirectories(TMP_OUTPUT_DIR); + Files.createDirectories(tmpOutputDir); for (String mockFile : new String[]{"hello_world.xml", "null_pointer.xml"}) { Files.copy(TikaPipesTest.class.getResourceAsStream("/test-documents/mock/" + mockFile), inputDir.resolve(mockFile)); } - TIKA_PIPES_LOG4j2_PATH = Files.createTempFile(TMP_DIR, "log4j2-", ".xml"); - Files.copy(TikaPipesTest.class.getResourceAsStream("/log4j2.xml"), TIKA_PIPES_LOG4j2_PATH, StandardCopyOption.REPLACE_EXISTING); - - TIKA_CONFIG_PATH = Files.createTempFile(TMP_DIR, "tika-pipes-config-", ".json"); + tikaPipesLog4j2Path = Files.createTempFile(tmpDir, "log4j2-", ".xml"); + Files.copy(TikaPipesTest.class.getResourceAsStream("/log4j2.xml"), tikaPipesLog4j2Path, StandardCopyOption.REPLACE_EXISTING); - CXFTestBase.createPluginsConfig(TIKA_CONFIG_PATH, inputDir, TMP_OUTPUT_DIR, null, 10000L); - } + tikaConfigPath = Files.createTempFile(tmpDir, "tika-pipes-config-", ".json"); + CXFTestBase.createPluginsConfig(tikaConfigPath, inputDir, tmpOutputDir, null, 10000L); - @AfterAll - public static void tearDownAfterClass() throws Exception { - FileUtils.deleteDirectory(TMP_DIR.toFile()); + // Now call parent setup which will use our config + super.setUp(); } @Override - @AfterEach + @AfterAll public void tearDown() throws Exception { if (pipesResource != null) { pipesResource.close(); pipesResource = null; } super.tearDown(); + if (tmpDir != null) { + FileUtils.deleteDirectory(tmpDir.toFile()); + } } @BeforeEach public void setUpEachTest() throws Exception { - if (Files.exists(TMP_OUTPUT_FILE)) { - Files.delete(TMP_OUTPUT_FILE); + if (Files.exists(tmpOutputFile)) { + Files.delete(tmpOutputFile); } - if (Files.exists(TMP_NPE_OUTPUT_FILE)) { - Files.delete(TMP_NPE_OUTPUT_FILE); + if (Files.exists(tmpNpeOutputFile)) { + Files.delete(tmpNpeOutputFile); } - assertFalse(Files.isRegularFile(TMP_OUTPUT_FILE)); + assertFalse(Files.isRegularFile(tmpOutputFile)); } @Override protected void setUpResources(JAXRSServerFactoryBean sf) { List<ResourceProvider> rCoreProviders = new ArrayList<>(); try { - pipesResource = new PipesResource(TIKA_CONFIG_PATH); + pipesResource = new PipesResource(tikaConfigPath); rCoreProviders.add(new SingletonResourceProvider(pipesResource)); } catch (IOException | TikaConfigException e) { throw new RuntimeException(e); @@ -155,7 +158,7 @@ public class TikaPipesTest extends CXFTestBase { @Override protected InputStream getTikaConfigInputStream() throws IOException { - return new ByteArrayInputStream(Files.readAllBytes(TIKA_CONFIG_PATH)); + return new ByteArrayInputStream(Files.readAllBytes(tikaConfigPath)); } @@ -182,7 +185,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - try (Reader reader = Files.newBufferedReader(TMP_OUTPUT_FILE)) { + try (Reader reader = Files.newBufferedReader(tmpOutputFile)) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(1, metadataList.size()); @@ -222,7 +225,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - try (Reader reader = Files.newBufferedReader(TMP_OUTPUT_FILE)) { + try (Reader reader = Files.newBufferedReader(tmpOutputFile)) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(1, metadataList.size()); @@ -265,7 +268,7 @@ public class TikaPipesTest extends CXFTestBase { .get("emitted") .asBoolean()); List<Metadata> metadataList; - try (Reader reader = Files.newBufferedReader(TMP_OUTPUT_DIR.resolve("null_pointer.xml.json"))) { + try (Reader reader = Files.newBufferedReader(tmpOutputDir.resolve("null_pointer.xml.json"))) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(1, metadataList.size()); @@ -303,6 +306,6 @@ public class TikaPipesTest extends CXFTestBase { assertFalse(jsonResponse .get("emitted") .asBoolean()); - assertFalse(Files.isRegularFile(TMP_NPE_OUTPUT_FILE)); + assertFalse(Files.isRegularFile(tmpNpeOutputFile)); } } diff --git a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java index 8e69634ff4..a388610894 100644 --- a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java +++ b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java @@ -42,11 +42,11 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; -import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.api.TestInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,6 +75,7 @@ import org.apache.tika.server.core.writer.JSONObjWriter; * This offers basic integration tests with fetchers and emitters. * We use file system fetchers and emitters. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TikaPipesTest extends CXFTestBase { private static final Logger LOG = LoggerFactory.getLogger(TikaPipesTest.class); @@ -83,52 +84,56 @@ public class TikaPipesTest extends CXFTestBase { private static final String TEST_RECURSIVE_DOC = "test_recursive_embedded.docx"; private static final String TEST_TWO_BOXES_PDF = "testPDFTwoTextBoxes.pdf"; - @TempDir - private static Path TMP_WORKING_DIR; - private static Path OUTPUT_JSON_DIR; - private static Path OUTPUT_BYTES_DIR; - private static Path TIKA_PIPES_LOG4j2_PATH; - private static Path TIKA_CONFIG_PATH; - private static FetcherManager FETCHER_MANAGER; + private Path tmpWorkingDir; + private Path outputJsonDir; + private Path outputBytesDir; + private Path tikaPipesLog4j2Path; + private Path tikaConfigPath; + private FetcherManager fetcherManager; private PipesResource pipesResource; + @Override @BeforeAll - public static void setUpBeforeClass() throws Exception { - Path inputDir = TMP_WORKING_DIR.resolve("input"); - OUTPUT_JSON_DIR = TMP_WORKING_DIR.resolve("output"); - OUTPUT_BYTES_DIR = TMP_WORKING_DIR.resolve("bytes"); + public void setUp() throws Exception { + // Initialize test directories and config before parent setup + tmpWorkingDir = Files.createTempDirectory("tika-pipes-test-"); + Path inputDir = tmpWorkingDir.resolve("input"); + outputJsonDir = tmpWorkingDir.resolve("output"); + outputBytesDir = tmpWorkingDir.resolve("bytes"); Files.createDirectories(inputDir); - Files.createDirectories(OUTPUT_JSON_DIR); + Files.createDirectories(outputJsonDir); Files.copy(TikaPipesTest.class.getResourceAsStream("/test-documents/" + TEST_RECURSIVE_DOC), inputDir.resolve("test_recursive_embedded.docx"), StandardCopyOption.REPLACE_EXISTING); Files.copy(TikaPipesTest.class.getResourceAsStream("/test-documents/" + TEST_TWO_BOXES_PDF), inputDir.resolve(TEST_TWO_BOXES_PDF), StandardCopyOption.REPLACE_EXISTING); - TIKA_PIPES_LOG4j2_PATH = Files.createTempFile(TMP_WORKING_DIR, "log4j2-", ".xml"); - Files.copy(TikaPipesTest.class.getResourceAsStream("/log4j2.xml"), TIKA_PIPES_LOG4j2_PATH, StandardCopyOption.REPLACE_EXISTING); + tikaPipesLog4j2Path = Files.createTempFile(tmpWorkingDir, "log4j2-", ".xml"); + Files.copy(TikaPipesTest.class.getResourceAsStream("/log4j2.xml"), tikaPipesLog4j2Path, StandardCopyOption.REPLACE_EXISTING); - TIKA_CONFIG_PATH = Files.createTempFile(TMP_WORKING_DIR, "tika-pipes-config-", ".json"); - CXFTestBase.createPluginsConfig(TIKA_CONFIG_PATH, inputDir, OUTPUT_JSON_DIR, OUTPUT_BYTES_DIR, 10000L); + tikaConfigPath = Files.createTempFile(tmpWorkingDir, "tika-pipes-config-", ".json"); + CXFTestBase.createPluginsConfig(tikaConfigPath, inputDir, outputJsonDir, outputBytesDir, 10000L); - TikaJsonConfig tikaJsonConfig = TikaJsonConfig.load(TIKA_CONFIG_PATH); + TikaJsonConfig tikaJsonConfig = TikaJsonConfig.load(tikaConfigPath); TikaPluginManager pluginManager = TikaPluginManager.load(tikaJsonConfig); - FETCHER_MANAGER = FetcherManager.load(pluginManager, tikaJsonConfig); + fetcherManager = FetcherManager.load(pluginManager, tikaJsonConfig); + // Now call parent setup which will use our config + super.setUp(); } @BeforeEach public void setUpEachTest() throws Exception { - FileUtils.deleteDirectory(OUTPUT_JSON_DIR.toFile()); - assertFalse(Files.isDirectory(OUTPUT_JSON_DIR)); + FileUtils.deleteDirectory(outputJsonDir.toFile()); + assertFalse(Files.isDirectory(outputJsonDir)); } @Override protected void setUpResources(JAXRSServerFactoryBean sf) { List<ResourceProvider> rCoreProviders = new ArrayList<>(); try { - pipesResource = new PipesResource(TIKA_CONFIG_PATH); + pipesResource = new PipesResource(tikaConfigPath); rCoreProviders.add(new SingletonResourceProvider(pipesResource)); } catch (IOException | TikaConfigException e) { throw new RuntimeException(e); @@ -137,13 +142,16 @@ public class TikaPipesTest extends CXFTestBase { } @Override - @AfterEach + @AfterAll public void tearDown() throws Exception { if (pipesResource != null) { pipesResource.close(); pipesResource = null; } super.tearDown(); + if (tmpWorkingDir != null) { + FileUtils.deleteDirectory(tmpWorkingDir.toFile()); + } } @Override @@ -156,12 +164,12 @@ public class TikaPipesTest extends CXFTestBase { @Override protected InputStream getTikaConfigInputStream() throws IOException { - return new ByteArrayInputStream(Files.readAllBytes(TIKA_CONFIG_PATH)); + return new ByteArrayInputStream(Files.readAllBytes(tikaConfigPath)); } @Override protected InputStream getPipesConfigInputStream() throws IOException { - return new ByteArrayInputStream(Files.readAllBytes(TIKA_CONFIG_PATH)); + return new ByteArrayInputStream(Files.readAllBytes(tikaConfigPath)); } @@ -181,7 +189,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - try (Reader reader = Files.newBufferedReader(OUTPUT_JSON_DIR.resolve(TEST_RECURSIVE_DOC + ".json"))) { + try (Reader reader = Files.newBufferedReader(outputJsonDir.resolve(TEST_RECURSIVE_DOC + ".json"))) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(12, metadataList.size()); @@ -210,7 +218,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - try (Reader reader = Files.newBufferedReader(OUTPUT_JSON_DIR.resolve(TEST_RECURSIVE_DOC + ".json"))) { + try (Reader reader = Files.newBufferedReader(outputJsonDir.resolve(TEST_RECURSIVE_DOC + ".json"))) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(1, metadataList.size()); @@ -237,7 +245,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - Path outputFile = OUTPUT_JSON_DIR.resolve(TEST_TWO_BOXES_PDF + ".json"); + Path outputFile = outputJsonDir.resolve(TEST_TWO_BOXES_PDF + ".json"); try (Reader reader = Files.newBufferedReader(outputFile)) { metadataList = JsonMetadataList.fromJson(reader); } @@ -282,7 +290,7 @@ public class TikaPipesTest extends CXFTestBase { assertEquals(200, response.getStatus()); List<Metadata> metadataList = null; - try (Reader reader = Files.newBufferedReader(OUTPUT_JSON_DIR.resolve(TEST_RECURSIVE_DOC + ".json"))) { + try (Reader reader = Files.newBufferedReader(outputJsonDir.resolve(TEST_RECURSIVE_DOC + ".json"))) { metadataList = JsonMetadataList.fromJson(reader); } assertEquals(12, metadataList.size()); @@ -290,7 +298,7 @@ public class TikaPipesTest extends CXFTestBase { .get(6) .get(TikaCoreProperties.TIKA_CONTENT)); Map<String, Long> expected = loadExpected(); - Map<String, Long> byteFileNames = getFileNames(OUTPUT_BYTES_DIR); + Map<String, Long> byteFileNames = getFileNames(outputBytesDir); assertEquals(expected, byteFileNames); } @@ -313,7 +321,7 @@ public class TikaPipesTest extends CXFTestBase { private Map<String, Long> getFileNames(Path p) throws Exception { final Map<String, Long> ret = new HashMap<>(); - Files.walkFileTree(OUTPUT_BYTES_DIR, new FileVisitor<Path>() { + Files.walkFileTree(outputBytesDir, new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { return FileVisitResult.CONTINUE;
