Author: tallison Date: Fri Feb 20 14:16:18 2015 New Revision: 1661129 URL: http://svn.apache.org/r1661129 Log: TIKA-1553: add an EvilParser for testing purposes
Added: tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/ tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParser.java tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParserTest.java tika/trunk/tika-parsers/src/test/resources/META-INF/ tika/trunk/tika-parsers/src/test/resources/META-INF/services/ tika/trunk/tika-parsers/src/test/resources/META-INF/services/org.apache.tika.parser.Parser tika/trunk/tika-parsers/src/test/resources/org/ tika/trunk/tika-parsers/src/test/resources/org/apache/ tika/trunk/tika-parsers/src/test/resources/org/apache/tika/ tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/ tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/custom-mimetypes.xml tika/trunk/tika-parsers/src/test/resources/test-documents/evil/ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/fake_oom.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/heavy_hang.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/nothing_bad.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer_no_msg.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/real_oom.evil tika/trunk/tika-parsers/src/test/resources/test-documents/evil/sleep.evil Modified: tika/trunk/CHANGES.txt tika/trunk/tika-parsers/src/test/java/org/apache/tika/TikaTest.java Modified: tika/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/tika/trunk/CHANGES.txt?rev=1661129&r1=1661128&r2=1661129&view=diff ============================================================================== --- tika/trunk/CHANGES.txt (original) +++ tika/trunk/CHANGES.txt Fri Feb 20 14:16:18 2015 @@ -1,10 +1,13 @@ Release 1.8 - Current Development + * Added EvilParser for testing handling of exceptions, errors + and hangs in code that uses parsers. (TIKA-1533) + * Increased the speed of language identification by a factor of two. (TIKA-1549) * Added parser for Sqlite3 db files. Users need to add - org.xerial's sqlite-jdbc to their classpath. Tika is not + org.xerial's sqlite-jdbc to their classpath!!! Tika is not currently bundling that dependency. (TIKA-1511) * Use POST instead of PUT for tika-server form methods. Modified: tika/trunk/tika-parsers/src/test/java/org/apache/tika/TikaTest.java URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/java/org/apache/tika/TikaTest.java?rev=1661129&r1=1661128&r2=1661129&view=diff ============================================================================== --- tika/trunk/tika-parsers/src/test/java/org/apache/tika/TikaTest.java (original) +++ tika/trunk/tika-parsers/src/test/java/org/apache/tika/TikaTest.java Fri Feb 20 14:16:18 2015 @@ -16,17 +16,9 @@ */ package org.apache.tika; -import org.apache.tika.extractor.EmbeddedResourceHandler; -import org.apache.tika.io.IOUtils; -import org.apache.tika.io.TikaInputStream; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MediaType; -import org.apache.tika.parser.AutoDetectParser; -import org.apache.tika.parser.ParseContext; -import org.apache.tika.parser.Parser; -import org.apache.tika.sax.BodyContentHandler; -import org.apache.tika.sax.ToXMLContentHandler; -import org.xml.sax.ContentHandler; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.File; @@ -39,9 +31,17 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.apache.tika.extractor.EmbeddedResourceHandler; +import org.apache.tika.io.IOUtils; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.sax.BodyContentHandler; +import org.apache.tika.sax.ToXMLContentHandler; +import org.xml.sax.ContentHandler; /** * Parent class of Tika tests @@ -99,6 +99,10 @@ public abstract class TikaTest { } } + protected XMLResult getXML(String filePath, Metadata metadata) throws Exception { + return getXML(getResourceAsStream("/test-documents/" + filePath), new AutoDetectParser(), metadata); + } + protected XMLResult getXML(String filePath) throws Exception { return getXML(getResourceAsStream("/test-documents/" + filePath), new AutoDetectParser(), new Metadata()); } Added: tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParser.java URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParser.java?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParser.java (added) +++ tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParser.java Fri Feb 20 14:16:18 2015 @@ -0,0 +1,228 @@ +package org.apache.tika.parser.evil; + +/* + * 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. + */ + + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.io.IOUtils; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AbstractParser; +import org.apache.tika.parser.ParseContext; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Parser to be used only for testing wrappers and drivers of Parsers. + * <p> + * This class enables tests for handling parsers that run into problems. + */ + +public class EvilParser extends AbstractParser { + + private static final long serialVersionUID = 1L; + + //NOTE: these are just regexes, attributes must be in proper order! + + //<throwable message="some message">java.lang.SomeException</throwable> + //<throwable>java.lang.SomeException</throwable> + private static final Pattern THROWABLE = + Pattern.compile("<throwable(?:\\s*message=\"([^\"]+)\")?\\s*>([^<>]+)</throwable>"); + + //<hang type="heavy" max_millis="1000" pulse_check_millis="100000000"/> + //<hang type="sleep" max_millis="1000"/> + private static final Pattern HANG = + Pattern.compile("<hang type=\"(heavy|sleep)\"\\s+max_millis=\"(\\d+)\"(?:\\s+pulse_check_millis=\"(\\d+)\")?\\s*/>"); + + //<real_oom/> + private final static Pattern REAL_OOM = Pattern.compile("<real_oom/>"); + + + @Override + public Set<MediaType> getSupportedTypes(ParseContext context) { + Set<MediaType> types = new HashSet<MediaType>(); + MediaType type = MediaType.application("evil"); + types.add(type); + return types; + } + + @Override + public void parse(InputStream stream, ContentHandler handler, + Metadata metadata, ParseContext context) throws IOException, + SAXException, TikaException { + String content = IOUtils.toString(stream, IOUtils.UTF_8.toString()); + + Matcher hangMatcher = HANG.matcher(content); + if (hangMatcher.find()) { + handleHang(hangMatcher); + handle(content, handler); + return; + } + Matcher throwableMatcher = THROWABLE.matcher(content); + if (throwableMatcher.find()) { + String msg = throwableMatcher.group(1); + String throwableClass = throwableMatcher.group(2); + throwIt(throwableClass, msg); + //exception should have been thrown by now + assert(false); + } + + Matcher realOOM = REAL_OOM.matcher(content); + if (realOOM.find()) { + kabOOM(); + } + + //if there has been no trigger, treat as + //regular utf-8 text file + handle(content, handler); + + } + + private void handleHang(Matcher hangMatcher) { + String hangType = hangMatcher.group(1); + + if (hangMatcher.group(2) == null) { + throw new RuntimeException("must specify max_millis attribute in <hang>"); + } + + long maxMillis = parseLong(hangMatcher.group(2)); + if ("heavy".equals(hangType)) { + if (hangMatcher.group(3) == null) { + throw new RuntimeException("must specify pulse_check_millis attribute in <hang> when type is heavy"); + } + long heavyHangPulseMillis = parseLong(hangMatcher.group(3)); + hangHeavy(maxMillis, heavyHangPulseMillis); + } else if ("sleep".equals(hangType)) { + sleep(maxMillis); + } else { + throw new RuntimeException("need to specify heavy|sleep as value to type attribute for <hang>"); + } + + } + + private long parseLong(String s) { + long millis = -1; + try { + millis = Long.parseLong(s); + } catch (NumberFormatException e) { + //shouldn't happen unless something goes wrong w regex + throw new RuntimeException("Problem in regex parsing sleep duration"); + } + return millis; + } + + private void throwIt(String className, String msg) throws IOException, + SAXException, TikaException { + Throwable t = null; + if (msg == null) { + try { + t = (Throwable) Class.forName(className).newInstance(); + } catch (Exception e) { + throw new RuntimeException("couldn't create throwable class:"+className, e); + } + } else { + try { + Class clazz = Class.forName(className); + Constructor con = clazz.getConstructor(String.class); + t = (Throwable) con.newInstance(msg); + } catch (Exception e) { + throw new RuntimeException("couldn't create throwable class:" + className, e); + } + } + if (t instanceof SAXException) { + throw (SAXException)t; + } else if (t instanceof IOException) { + throw (IOException) t; + } else if (t instanceof TikaException) { + throw (TikaException) t; + } else if (t instanceof Error) { + throw (Error) t; + } else if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + //wrap the throwable in a RuntimeException + throw new RuntimeException(t); + } + } + + private void handle(String content, ContentHandler handler) throws SAXException { + + handler.startDocument(); + Attributes attrs = new AttributesImpl(); + handler.startElement("", "body", "body", attrs); + handler.startElement("", "p", "p", attrs); + char[] charArr = content.toCharArray(); + handler.characters(charArr, 0, charArr.length); + handler.endElement("", "p", "p"); + handler.endElement("", "body", "body"); + handler.endDocument(); + + } + + private void kabOOM() { + List<int[]> ints = new ArrayList<int[]>(); + + while (true) { + int[] intArr = new int[32000]; + ints.add(intArr); + } + } + + private void hangHeavy(long maxMillis, long pulseCheckMillis) { + //do some heavy computation and occasionally check for + //whether time has exceeded maxMillis. see TIKA-1132 for inspiration + long start = new Date().getTime(); + int lastChecked = 0; + while (true) { + for (int i = 1; i < Integer.MAX_VALUE; i++) { + for (int j = 1; j < Integer.MAX_VALUE; j++) { + double div = (double) i / (double) j; + lastChecked++; + if (lastChecked > pulseCheckMillis) { + lastChecked = 0; + long elapsed = new Date().getTime()-start; + if (elapsed > maxMillis) { + return; + } + } + } + } + } + } + + private void sleep(long maxMillis) { + try { + Thread.sleep(maxMillis); + } catch (InterruptedException e) { + + } + } +} \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParserTest.java URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParserTest.java?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParserTest.java (added) +++ tika/trunk/tika-parsers/src/test/java/org/apache/tika/parser/evil/EvilParserTest.java Fri Feb 20 14:16:18 2015 @@ -0,0 +1,159 @@ +package org.apache.tika.parser.evil; + +/* + * 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. + */ + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNull; +import static junit.framework.TestCase.assertTrue; + +import java.util.Date; + +import org.apache.tika.TikaTest; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.junit.Test; + +public class EvilParserTest extends TikaTest { + + @Test + public void testNothingBad() throws Exception { + //For use cases that need to modify the mime types and potentially + //pass a non-evil document through the EvilParser. + + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "nothing_bad.evil"); + String content = getXML("evil/nothing_bad.evil", m).xml; + + assertContains("Whan that Aprille", content); + assertEvilParser(m); + } + + @Test + public void testNullPointer() throws Exception { + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "null_pointer.evil"); + boolean ex = false; + try { + String content = getXML("evil/null_pointer.evil", m).xml; + //runtime exceptions are wrapped in a TikaException by CompositeParser + } catch (TikaException e) { + if (e.getCause() != null && e.getCause() instanceof java.lang.NullPointerException) { + String msg = e.getCause().getMessage(); + assertEquals("null pointer message", msg); + ex = true; + } + } + assertTrue("NullPointerException", ex); + } + + @Test + public void testNullPointerNoMsg() throws Exception { + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "null_pointer_no_msg.evil"); + boolean ex = false; + try { + String content = getXML("evil/null_pointer_no_msg.evil", m).xml; + //runtime exceptions are wrapped in a TikaException by CompositeParser + } catch (TikaException e) { + if (e.getCause() != null && e.getCause() instanceof java.lang.NullPointerException) { + String msg = e.getCause().getMessage(); + assertNull(msg); + ex = true; + } + } + assertTrue("NullPointerException with no msg", ex); + } + + + @Test + public void testSleep() throws Exception { + long start = new Date().getTime(); + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "sleep.evil"); + String content = getXML("evil/sleep.evil", m).xml; + assertEvilParser(m); + long elapsed = new Date().getTime()-start; + //should sleep for at least 3000 + boolean enoughTimeHasElapsed = elapsed > 2000; + assertTrue("enough time has not elapsed: "+elapsed, enoughTimeHasElapsed); + } + + @Test + public void testHeavyHang() throws Exception { + long start = new Date().getTime(); + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "heavy_hang.evil"); + String content = getXML("evil/heavy_hang.evil", m).xml; + assertEvilParser(m); + long elapsed = new Date().getTime()-start; + //should sleep for at least 3000 + boolean enoughTimeHasElapsed = elapsed > 2000; + assertTrue("enough time has elapsed: "+elapsed, enoughTimeHasElapsed); + } + + @Test + public void testFakeOOM() throws Exception { + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "fake_oom.evil"); + boolean ex = false; + try { + String content = getXML("evil/fake_oom.evil", m).xml; + } catch (OutOfMemoryError e) { + assertEquals("fake oom", e.getMessage()); + ex = true; + } + assertTrue("Fake oom", ex); + } + + @Test + public void testRealOOM() throws Exception { + //this doesn't actually test real oom, but + //only relies on the message + + Metadata m = new Metadata(); + //need to set resource name so that detector can work + m.set(Metadata.RESOURCE_NAME_KEY, "real_oom.evil"); + boolean ex = false; + try { + String content = getXML("evil/real_oom.evil", m).xml; + } catch (OutOfMemoryError e) { + assertContains("Java heap space", e.getMessage()); + ex = true; + } + assertTrue("Real oom", ex); + } + + private void assertEvilParser(Metadata m) { + String[] parsers = m.getValues("X-Parsed-By"); + //make sure that it was actually parsed by evil. + boolean parsedByEvil = false; + for (String parser : parsers) { + if (parser.equals("org.apache.tika.parser.evil.EvilParser")) { + parsedByEvil = true; + break; + } + } + assertTrue("evil parser should have been called", parsedByEvil); + } +} Added: tika/trunk/tika-parsers/src/test/resources/META-INF/services/org.apache.tika.parser.Parser URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/META-INF/services/org.apache.tika.parser.Parser?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/META-INF/services/org.apache.tika.parser.Parser (added) +++ tika/trunk/tika-parsers/src/test/resources/META-INF/services/org.apache.tika.parser.Parser Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +org.apache.tika.parser.evil.EvilParser \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/custom-mimetypes.xml URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/custom-mimetypes.xml?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/custom-mimetypes.xml (added) +++ tika/trunk/tika-parsers/src/test/resources/org/apache/tika/mime/custom-mimetypes.xml Fri Feb 20 14:16:18 2015 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info> + <mime-type type="application/evil"> + <glob pattern="*.evil"/> + <sub-class-of type="text/plain"/> + </mime-type> +</mime-info> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/fake_oom.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/fake_oom.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/fake_oom.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/fake_oom.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<throwable message="fake oom">java.lang.OutOfMemoryError</throwable> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/heavy_hang.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/heavy_hang.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/heavy_hang.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/heavy_hang.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<hang type="heavy" max_millis="3000" pulse_check_millis="100000000"/> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/nothing_bad.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/nothing_bad.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/nothing_bad.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/nothing_bad.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1,18 @@ +Whan that Aprille with his shoures soote +The droghte of Marche hath perced to the roote, +And bathed every veyne in swich licour, +Of which vertu engendred is the flour; +Whan Zephirus eek with his swete breeth +Inspired hath in every holt and heeth +The tendre croppes, and the yonge sonne +Hath in the Ram his halfe cours y-ronne, +And smale fowles maken melodye, +That slepen al the night with open ye, +(So priketh hem nature in hir corages: +Than longen folk to goon on pilgrimages, +And palmers for to seken straunge strondes, +To ferne halwes, couthe in sondry londes; +And specially, from every shires ende +Of Engelond, to Caunterbury they wende, +The holy blisful martir for to seke, +That hem hath holpen, whan that they were seke. \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<throwable message="null pointer message">java.lang.NullPointerException</throwable> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer_no_msg.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer_no_msg.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer_no_msg.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/null_pointer_no_msg.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<throwable>java.lang.NullPointerException</throwable> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/real_oom.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/real_oom.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/real_oom.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/real_oom.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<real_oom/> \ No newline at end of file Added: tika/trunk/tika-parsers/src/test/resources/test-documents/evil/sleep.evil URL: http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/test/resources/test-documents/evil/sleep.evil?rev=1661129&view=auto ============================================================================== --- tika/trunk/tika-parsers/src/test/resources/test-documents/evil/sleep.evil (added) +++ tika/trunk/tika-parsers/src/test/resources/test-documents/evil/sleep.evil Fri Feb 20 14:16:18 2015 @@ -0,0 +1 @@ +<hang type="sleep" max_millis="3000"/> \ No newline at end of file