handle zero and negative thresholds (#587)

diff --git a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
index 8102eb5..e5b8d5a 100644
--- a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
@@ -23,9 +23,12 @@
 import org.apache.commons.io.function.IOFunction;
 
 /**
- * An output stream which triggers an event when a specified number of bytes of data have been written to it. The event
- * can be used, for example, to throw an exception if a maximum has been reached, or to switch the underlying stream
- * type when the threshold is exceeded.
+ * An output stream which triggers an event on the first write that causes
+ * the total number of bytes written to the stream to exceed a configured threshold,
+ * and every subsequent write. The event
+ * can be used, for example, to throw an exception if a maximum has been reached,
+ * or to switch the underlying stream when the threshold is exceeded.
+ *
  * <p>
  * This class overrides all {@link OutputStream} methods. However, these overrides ultimately call the corresponding
  * methods in the underlying output stream implementation.
@@ -89,6 +92,9 @@
         this.threshold = threshold;
         this.thresholdConsumer = thresholdConsumer == null ? IOConsumer.noop() : thresholdConsumer;
         this.outputStreamGetter = outputStreamGetter == null ? NOOP_OS_GETTER : outputStreamGetter;
+        if (threshold < 0) {
+            thresholdExceeded = true;
+        }
     }
 
     /**
@@ -244,6 +250,8 @@
     @SuppressWarnings("resource") // the underlying stream is managed by a subclass.
     @Override
     public void write(final byte[] b, final int off, final int len) throws IOException {
+        // TODO we could write the sub-array up the threshold, fire the event,
+        // and then write the rest so the event is always fired at the precise point.
         checkThreshold(len);
         // TODO for 4.0: Replace with getOutputStream()
         getStream().write(b, off, len);
diff --git a/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java b/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
index 080a492..efa67b4 100644
--- a/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
@@ -33,6 +33,29 @@
 public class ThresholdingOutputStreamTest {
 
     @Test
+    public void testThresholdLessThanZero() throws IOException {
+        try (final ThresholdingOutputStream out = new ThresholdingOutputStream(-1)) {
+            assertTrue(out.isThresholdExceeded());
+        }
+    }
+
+    @Test
+    public void testThresholdZero() throws IOException {
+        final AtomicBoolean reached = new AtomicBoolean(false);
+        try (final ThresholdingOutputStream out = new ThresholdingOutputStream(0) {
+            @Override
+            protected void thresholdReached() throws IOException {
+                reached.set(true);
+            }
+        }) {
+            assertFalse(out.isThresholdExceeded());
+            out.write(89);
+            assertTrue(reached.get());
+            assertTrue(out.isThresholdExceeded());
+        }
+    }
+
+    @Test
     public void testSetByteCount_OutputStream() throws Exception {
         final AtomicBoolean reached = new AtomicBoolean(false);
         try (ThresholdingOutputStream tos = new ThresholdingOutputStream(3) {