PDFBoxRendererTest.java
/*
* 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.renderer.pdf.pdfbox;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.pdf.PDFParserConfig;
import org.apache.tika.renderer.PageBasedRenderResults;
import org.apache.tika.renderer.PageRangeRequest;
import org.apache.tika.renderer.RenderResult;
@Isolated // testFailedRenderLeavesNoTempFiles snapshots java.io.tmpdir
public class PDFBoxRendererTest {
private long renderedPngBytes(ParseContext context) throws Exception {
PDFBoxRenderer renderer = new PDFBoxRenderer();
try (InputStream is = getClass().getResourceAsStream("/test-documents/testPDF.pdf");
TikaInputStream tis = TikaInputStream.get(is)) {
assertNotNull(is);
PageBasedRenderResults results = (PageBasedRenderResults) renderer.render(
tis, new Metadata(), context, new PageRangeRequest(1, 1));
RenderResult r = results.getResults().get(0);
assertEquals(RenderResult.STATUS.SUCCESS, r.getStatus());
try (TikaInputStream img = r.getInputStream()) {
byte[] b = img.readAllBytes();
assertEquals((byte) 0x89, b[0]);
assertEquals((byte) 'P', b[1]);
results.close();
return b.length;
}
}
}
@Test
public void testPngCompressedByDefault() throws Exception {
// letter page, 300 dpi gray: raw raster ~8.5 MB; compressed must be far smaller
long bytes = renderedPngBytes(new ParseContext());
assertTrue(bytes < 2_000_000, "default render should be a compressed PNG, got " + bytes);
}
@Test
public void testImageQualityConfigurable() throws Exception {
// ImageIO's PNG "quality" 1.0 = uncompressed; proves the config reaches the writer
PDFParserConfig config = new PDFParserConfig();
config.getOcr().setImageQuality(1.0f);
ParseContext context = new ParseContext();
context.set(PDFParserConfig.class, config);
long uncompressed = renderedPngBytes(context);
long compressed = renderedPngBytes(new ParseContext());
assertTrue(uncompressed > compressed * 4,
"quality 1.0 should be far larger: " + uncompressed + " vs " + compressed);
}
/** An out-of-range page throws past the per-page IOException catch after RENDER_ALL wrote pages. */
@Test
public void testFailedRenderLeavesNoTempFiles() throws Exception {
PDFBoxRenderer renderer = new PDFBoxRenderer();
Set<String> before = tikaTempEntries();
try (InputStream is = getClass().getResourceAsStream("/test-documents/testPDF.pdf");
TikaInputStream tis = TikaInputStream.get(is)) {
assertThrows(RuntimeException.class, () -> renderer.render(tis, new Metadata(),
new ParseContext(), PageRangeRequest.RENDER_ALL, new PageRangeRequest(9999, 9999)));
}
Set<String> leaked = tikaTempEntries();
leaked.removeAll(before);
assertTrue(leaked.isEmpty(), "temp files left behind: " + leaked);
}
private static Set<String> tikaTempEntries() throws IOException {
Set<String> names = new HashSet<>();
Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"));
try (DirectoryStream<Path> entries = Files.newDirectoryStream(tmpDir, "tika-pdfbox-rendering-*")) {
for (Path p : entries) {
names.add(p.getFileName().toString());
}
}
return names;
}
}