ImageChecksConfigTest.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.imageprocessing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.tika.config.loader.TikaLoader;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.enricher.CompositeContentEnricher;
import org.apache.tika.parser.enricher.GatedEnricher;
import org.apache.tika.parser.mock.MockEnricher;
/** The checks as a deployment lists them: by name under a "text-recognizers" entry. */
public class ImageChecksConfigTest {
@TempDir
Path tmp;
private Parser engine(String entry) throws Exception {
Path config = tmp.resolve("tika-config.json");
Files.writeString(config, "{ \"engines\": { \"png\": { \"mock-enricher\": {} } },"
+ " \"text-recognizers\": [ " + entry + " ] }");
List<Parser> matched = TikaLoader.load(config).get(CompositeContentEnricher.class)
.getEnrichers(MediaType.image("png"));
assertEquals(1, matched.size());
return matched.get(0);
}
private static Metadata read(Parser engine, byte[] image) throws Exception {
Metadata metadata = new Metadata();
try (TikaInputStream tis = TikaInputStream.get(image)) {
engine.parse(tis, new DefaultHandler(), metadata, new ParseContext());
}
return metadata;
}
@Test
public void testNamedChecksWrapTheEngineOnce() throws Exception {
Parser engine = engine("{ \"engine\": \"png\", \"_min-width\": 8, \"checks\": ["
+ " {\"min-image-size\": {}}, {\"blank-image-check\": {\"maxInk\": 0.001}} ] }");
GatedEnricher gate = (GatedEnricher) engine;
// the recorded-size minimum, then the two named checks, in one decorator
assertEquals(3, gate.getChecks().size());
assertTrue(gate.getChecks().get(1) instanceof MinImageSizeCheck);
assertTrue(gate.getChecks().get(2) instanceof BlankImageCheck);
}
@Test
public void testABlankImageNeverReachesTheEngine() throws Exception {
Parser engine = engine("{ \"engine\": \"png\", \"checks\": [ \"blank-image-check\" ] }");
Metadata m = read(engine, ImageFixtures.png(200, 200, 0));
assertNull(m.get(MockEnricher.MARKER_KEY));
assertEquals("skipped:blank", m.get(TikaCoreProperties.OCR_WARNINGS));
}
@Test
public void testAnImageWithInkReachesTheEngine() throws Exception {
Parser engine = engine("{ \"engine\": \"png\", \"checks\": ["
+ " {\"min-image-size\": {}}, {\"blank-image-check\": {}} ] }");
Metadata m = read(engine, ImageFixtures.png(200, 200, 0.2));
assertEquals("ENRICHED", m.get(MockEnricher.MARKER_KEY));
assertNull(m.get(TikaCoreProperties.OCR_WARNINGS));
}
@Test
public void testChecksRunInTheOrderListedAndTheFirstRefusalWins() throws Exception {
// a blank 20x20 image is too small and blank; the order decides the reason
byte[] tiny = ImageFixtures.png(20, 20, 0);
Parser sizeFirst = engine("{ \"engine\": \"png\", \"checks\": ["
+ " \"min-image-size\", \"blank-image-check\" ] }");
assertEquals("skipped:image-too-small",
read(sizeFirst, tiny).get(TikaCoreProperties.OCR_WARNINGS));
Parser blankFirst = engine("{ \"engine\": \"png\", \"checks\": ["
+ " \"blank-image-check\", \"min-image-size\" ] }");
assertEquals("skipped:blank",
read(blankFirst, tiny).get(TikaCoreProperties.OCR_WARNINGS));
}
@Test
public void testTheInlineFormTakesChecksToo() throws Exception {
Parser engine = engine("{ \"mock-enricher\": { \"checks\": [ \"blank-image-check\" ] } }");
assertEquals("skipped:blank", read(engine, ImageFixtures.png(200, 200, 0))
.get(TikaCoreProperties.OCR_WARNINGS));
}
@Test
public void testSettingsAreBoundToTheCheck() throws Exception {
Parser engine = engine("{ \"engine\": \"png\", \"checks\": ["
+ " {\"min-image-size\": {\"minWidthPixels\": 300, \"minHeightPixels\": 0, \"minTotalPixels\": 0}} ] }");
assertEquals("skipped:image-too-small", read(engine, ImageFixtures.png(200, 200, 0.5))
.get(TikaCoreProperties.OCR_WARNINGS));
assertEquals("ENRICHED", read(engine, ImageFixtures.png(400, 50, 0.5))
.get(MockEnricher.MARKER_KEY));
}
@Test
public void testByteSizeCheckByName() throws Exception {
Parser engine = engine("{ \"engine\": \"png\", \"checks\": ["
+ " {\"byte-size\": {\"minBytes\": 1000000}} ] }");
assertEquals("skipped:file-too-small", read(engine, ImageFixtures.png(200, 200, 0.5))
.get(TikaCoreProperties.OCR_WARNINGS));
}
@Test
public void testAnUnknownCheckFailsLoad() {
assertThrows(TikaConfigException.class, () -> engine("{ \"engine\": \"png\","
+ " \"checks\": [ \"no-such-check\" ] }"));
}
@Test
public void testChecksMustBeAnArray() {
TikaConfigException e = assertThrows(TikaConfigException.class, () -> engine(
"{ \"engine\": \"png\", \"checks\": \"blank-image-check\" }"));
assertTrue(e.getMessage().contains("must be an array"), e.getMessage());
}
@Test
public void testACheckWithTwoNamesFailsLoad() {
TikaConfigException e = assertThrows(TikaConfigException.class, () -> engine(
"{ \"engine\": \"png\", \"checks\": ["
+ " {\"min-image-size\": {}, \"blank-image-check\": {}} ] }"));
assertTrue(e.getMessage().contains("a \"checks\" member"), e.getMessage());
}
@Test
public void testAComponentThatIsNotACheckFailsLoad() {
assertThrows(TikaConfigException.class, () -> engine("{ \"engine\": \"png\","
+ " \"checks\": [ \"mock-enricher\" ] }"));
}
}