This is an automated email from the ASF dual-hosted git repository.

vanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-crypto.git


The following commit(s) were added to refs/heads/master by this push:
     new d8cbe88  JaCoCo Increase for Streams (#99)
d8cbe88 is described below

commit d8cbe8860d6f23548522e1bf5e8c74d5fd89122e
Author: aremily <arem...@users.noreply.github.com>
AuthorDate: Wed May 6 20:37:37 2020 -0400

    JaCoCo Increase for Streams (#99)
---
 .../crypto/stream/AbstractCipherStreamTest.java    | 399 +++++++++++++++++++--
 .../commons/crypto/stream/CtrCryptoStreamTest.java | 134 +++++++
 .../stream/PositionedCryptoInputStreamTest.java    |  37 +-
 3 files changed, 540 insertions(+), 30 deletions(-)

diff --git 
a/src/test/java/org/apache/commons/crypto/stream/AbstractCipherStreamTest.java 
b/src/test/java/org/apache/commons/crypto/stream/AbstractCipherStreamTest.java
index 344fc0d..8d585a6 100644
--- 
a/src/test/java/org/apache/commons/crypto/stream/AbstractCipherStreamTest.java
+++ 
b/src/test/java/org/apache/commons/crypto/stream/AbstractCipherStreamTest.java
@@ -17,6 +17,8 @@
  */
 package org.apache.commons.crypto.stream;
 
+import static org.junit.Assert.assertEquals;
+
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -27,10 +29,13 @@ import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
+import java.security.Key;
 import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.Properties;
 import java.util.Random;
 
+import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
@@ -44,9 +49,9 @@ import org.junit.Test;
 
 public abstract class AbstractCipherStreamTest {
 
-    private final int dataLen = 20000;
-    private final byte[] data = new byte[dataLen];
-    private byte[] encData;
+    protected final int dataLen = 20000;
+    protected final byte[] data = new byte[dataLen];
+    protected byte[] encData;
     private final Properties props = new Properties();
     protected byte[] key = new byte[16];
     protected byte[] iv = new byte[16];
@@ -98,6 +103,26 @@ public abstract class AbstractCipherStreamTest {
         doByteBufferWrite(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
         doByteBufferWrite(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, 
true);
     }
+    
+    @Test(timeout = 120000)
+    public void testExceptions() throws Exception {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        doExceptionTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, false);
+        doExceptionTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, 
false);
+
+        doExceptionTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
+        doExceptionTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, 
true);
+    }
+    
+    @Test(timeout = 120000)
+    public void testFieldGetters() throws Exception {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        doFieldGetterTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, 
false);
+        doFieldGetterTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, 
false);
+
+        doFieldGetterTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
+        doFieldGetterTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, 
true);
+    }
 
     protected void doSkipTest(final String cipherClass, final boolean 
withChannel)
             throws IOException {
@@ -110,9 +135,11 @@ public abstract class AbstractCipherStreamTest {
                 new ByteArrayInputStream(encData), getCipher(cipherClass),
                 defaultBufferSize, iv, withChannel)) {
             final byte[] result = new byte[dataLen];
-            final int n1 = readAll(in, result, 0, dataLen / 3);
+            final int n1 = readAll(in, result, 0, dataLen / 5);
 
-            long skipped = in.skip(dataLen / 3);
+            Assert.assertEquals(in.skip(0), 0);
+            
+            long skipped = in.skip(dataLen / 5);
             final int n2 = readAll(in, result, 0, dataLen);
 
             Assert.assertEquals(dataLen, n1 + skipped + n2);
@@ -197,46 +224,261 @@ public abstract class AbstractCipherStreamTest {
                 getCipher(cipherClass), smallBufferSize, iv, withChannel);
         buf.clear();
         byteBufferReadCheck(in, buf, 11);
+        in.close();      
+        
+        // Direct buffer, small buffer size, initial buffer position is 0, 
final read
+        in = getCryptoInputStream(new ByteArrayInputStream(encData),
+                getCipher(cipherClass), smallBufferSize, iv, withChannel);
+        buf.clear();
+        byteBufferFinalReadCheck(in, buf, 0);
+        in.close();
+        
+        // Default buffer size, initial buffer position is 0, insufficient 
dest buffer length
+        in = getCryptoInputStream(new ByteArrayInputStream(encData),
+                getCipher(cipherClass), defaultBufferSize, iv, withChannel);
+        buf = ByteBuffer.allocate(100);
+        byteBufferReadCheck(in, buf, 0);
+        in.close();
+        
+        // Default buffer size, initial buffer position is 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf = ByteBuffer.allocate(dataLen + 100);
+        byteBufferReadCheck(in, buf, 0);
+        in.close();
+        
+        // Default buffer size, initial buffer position is not 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 11);
+        in.close();
+
+        // Small buffer size, initial buffer position is 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 0);
+        in.close();
+
+        // Small buffer size, initial buffer position is not 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 11);
+        in.close();
+
+        // Direct buffer, default buffer size, initial buffer position is 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf = ByteBuffer.allocateDirect(dataLen + 100);
+        byteBufferReadCheck(in, buf, 0);
+        in.close();
+
+        // Direct buffer, default buffer size, initial buffer position is not 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 11);
+        in.close();
+
+        // Direct buffer, small buffer size, initial buffer position is 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 0);
+        in.close();
+
+        // Direct buffer, small buffer size, initial buffer position is not 0
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferReadCheck(in, buf, 11);
+        in.close();
+        
+        // Direct buffer, default buffer size, initial buffer position is 0, 
final read
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf.clear();
+        byteBufferFinalReadCheck(in, buf, 0);
+        in.close();
+        
+        // Default buffer size, initial buffer position is 0, insufficient 
dest buffer length
+        in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), key, 
+                new IvParameterSpec(iv), withChannel);
+        buf = ByteBuffer.allocate(100);
+        byteBufferReadCheck(in, buf, 0);
         in.close();
     }
 
     protected void doByteBufferWrite(final String cipherClass,
-            final ByteArrayOutputStream baos, final boolean withChannel) 
throws Exception {
+            final ByteArrayOutputStream baos, final boolean withChannel) 
+                throws Exception {
         if (AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME.equals(cipherClass)) {
             if (!Crypto.isNativeCodeLoaded()) {
                 return; // Skip this test if no JNI
             }
         }
         baos.reset();
-        final CryptoOutputStream out = getCryptoOutputStream(baos,
+        CryptoOutputStream out = getCryptoOutputStream(baos,
                 getCipher(cipherClass), defaultBufferSize, iv, withChannel);
-        ByteBuffer buf = ByteBuffer.allocateDirect(dataLen / 2);
-        buf.put(data, 0, dataLen / 2);
-        buf.flip();
-        final int n1 = out.write(buf);
-
-        buf.clear();
-        buf.put(data, n1, dataLen / 3);
-        buf.flip();
-        final int n2 = out.write(buf);
-
-        buf.clear();
-        buf.put(data, n1 + n2, dataLen - n1 - n2);
-        buf.flip();
-        final int n3 = out.write(buf);
-
-        Assert.assertEquals(dataLen, n1 + n2 + n3);
+        doByteBufferWrite(out, withChannel);
+        
+        baos.reset();
+        CryptoCipher cipher = getCipher(cipherClass);
+        String transformation = cipher.getAlgorithm();
+        out = getCryptoOutputStream(transformation, props, baos, key, 
+                new IvParameterSpec(iv), withChannel);
+        doByteBufferWrite(out, withChannel);
+        out.write(1);
+        Assert.assertTrue(out.isOpen()); 
+        
+        out = getCryptoOutputStream(transformation, props, baos, key, 
+                new IvParameterSpec(iv), withChannel);
+        out.close();
+        Assert.assertTrue(!out.isOpen());
+    }
 
-        out.flush();
+    protected void doExceptionTest(final String cipherClass, 
ByteArrayOutputStream baos,
+            final boolean withChannel) throws IOException {
+        if (AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME.equals(cipherClass)) {
+            if (!Crypto.isNativeCodeLoaded()) {
+                return; // Skip this test if no JNI
+            }
+        }
+        
+        InputStream in = null;
+        OutputStream out = null;
+        
+        // Test InvalidAlgorithmParameters
+        try {
+               in = getCryptoInputStream(transformation, props, new 
ByteArrayInputStream(encData), 
+                    new SecretKeySpec(key, "AES"), new GCMParameterSpec(0, new 
byte[0]), 
+                    withChannel);
+            Assert.fail("Expected IOException.");
+        } catch (IOException ex) {
+            Assert.assertEquals(ex.getMessage(),"Illegal parameters");
+        } 
+        
+        // Test InvalidAlgorithmParameters
+        try {
+            out = getCryptoOutputStream(transformation, props, baos, 
+                    new SecretKeySpec(key, "AES"), new GCMParameterSpec(0, 
+                    new byte[0]), withChannel);
+            Assert.fail("Expected IOException.");
+        } catch (IOException ex) {
+               Assert.assertEquals(ex.getMessage(),"Illegal parameters");
+        } 
+        
+        // Test Invalid Key
+        try {
+            in = getCryptoInputStream(transformation,props, new 
ByteArrayInputStream(encData), 
+                    new SecretKeySpec(new byte[10], "AES"), new 
IvParameterSpec(iv), withChannel);
+            Assert.fail("Expected IOException for Invalid Key");
+        } catch (IOException ex) {
+            Assert.assertNotNull(ex);
+        }
+        
+        // Test Invalid Key
+        try {
+            out = getCryptoOutputStream(transformation, props, baos, new 
byte[10], 
+                    new IvParameterSpec(iv), withChannel);
+            Assert.fail("Expected IOException for Invalid Key");
+        } catch (IOException ex) {
+            Assert.assertNotNull(ex);
+        }
+        
+        // Test reading a closed stream.
+        try { 
+            in = getCryptoInputStream(new ByteArrayInputStream(encData), 
+                    getCipher(cipherClass), defaultBufferSize, iv, 
withChannel);
+            in.close();
+            in.read(); // Throw exception.
+        } catch (IOException ex) {
+            Assert.assertTrue(ex.getMessage().equals("Stream closed"));
+        } 
+        
+        // Test closing a closed stream.
+        try { 
+            in.close(); // Don't throw exception on double-close.
+        } catch (IOException ex) {
+            Assert.fail("Should not throw exception closing a closed stream.");
+        } 
+
+        // Test checking a closed stream.
+        try { 
+            out = getCryptoOutputStream(transformation, props, baos, key, new 
IvParameterSpec(iv), 
+                    withChannel);
+            out.close();
+            ((CryptoOutputStream)out).checkStream(); // Throw exception.
+        } catch (IOException ex) {
+            Assert.assertTrue(ex.getMessage().equals("Stream closed"));
+        } 
+
+        // Test closing a closed stream.
+        try { 
+            out.close(); // Don't throw exception.
+        } catch (IOException ex) {
+            Assert.fail("Should not throw exception closing a closed stream.");
+        } 
+        
+        // Test checkStreamCipher
+        try { 
+            CryptoInputStream.checkStreamCipher(getCipher(cipherClass));
+        } catch (IOException ex) {
+            Assert.assertTrue(ex.getMessage().equals("AES/CTR/NoPadding is 
required"));
+        } finally {
+            in.close();
+        }
 
-        try (InputStream in = getCryptoInputStream(
-                new ByteArrayInputStream(encData), getCipher(cipherClass),
-                defaultBufferSize, iv, withChannel)) {
-            buf = ByteBuffer.allocate(dataLen + 100);
-            byteBufferReadCheck(in, buf, 0);
+        // Test unsupported operation handling.
+        try { 
+            in = getCryptoInputStream(new ByteArrayInputStream(encData), 
+                    getCipher(cipherClass), defaultBufferSize, iv, false);
+            in.mark(0);
+            assertEquals(false, in.markSupported());
+            in.reset();
+            Assert.fail("Expected IOException.");
+        } catch (IOException ex) {
+            Assert.assertTrue(ex.getMessage().equals("Mark/reset not 
supported"));
+        } finally {
+            in.close();
         }
     }
 
+    protected void doFieldGetterTest(final String cipherClass, 
ByteArrayOutputStream baos,
+            final boolean withChannel) throws Exception {
+        if (AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME.equals(cipherClass)) {
+            if (!Crypto.isNativeCodeLoaded()) {
+                return; // Skip this test if no JNI
+            }
+        }
+        
+        CryptoCipher cipher = getCipher(cipherClass);
+        
+        CryptoInputStream in = getCryptoInputStream(
+                new ByteArrayInputStream(encData), cipher, defaultBufferSize, 
+                iv, withChannel); 
+
+        Properties props = new Properties();
+        String bufferSize = Integer.toString(defaultBufferSize / 2);
+        props.put(CryptoInputStream.STREAM_BUFFER_SIZE_KEY, bufferSize);
+
+        Assert.assertEquals(CryptoInputStream.getBufferSize(props), 
Integer.parseInt(bufferSize));
+        Assert.assertEquals(in.getBufferSize(), defaultBufferSize);
+        Assert.assertEquals(in.getCipher().getClass(), 
Class.forName(cipherClass));
+        Assert.assertEquals(in.getKey().getAlgorithm(), "AES");
+        Assert.assertEquals(in.getParams().getClass(), IvParameterSpec.class);
+        Assert.assertNotNull(in.getInput());
+
+        CryptoOutputStream out = getCryptoOutputStream(baos, 
getCipher(cipherClass), 
+                defaultBufferSize, iv, withChannel);
+
+        Assert.assertEquals(out.getOutBuffer().capacity(), defaultBufferSize + 
cipher.getBlockSize());
+        Assert.assertEquals(out.getInBuffer().capacity(), defaultBufferSize);
+        Assert.assertEquals(out.getBufferSize(), defaultBufferSize);
+    }
+    
     private void byteBufferReadCheck(final InputStream in, final ByteBuffer 
buf, final int bufPos)
             throws Exception {
         buf.position(bufPos);
@@ -249,6 +491,30 @@ public abstract class AbstractCipherStreamTest {
         final byte[] expectedData = new byte[n];
         System.arraycopy(data, 0, expectedData, 0, n);
         Assert.assertArrayEquals(readData, expectedData);
+
+        try {
+            in.read(readData, -1, 0);
+            Assert.fail("Expected IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException ex) {
+            Assert.assertNotNull(ex);
+        }
+    }
+
+    private void byteBufferFinalReadCheck(final InputStream in, final 
ByteBuffer buf, final int bufPos)
+            throws Exception {
+        buf.position(bufPos);
+        int len = 0;
+        int n = 0;
+        do {
+            n = ((ReadableByteChannel) in).read(buf);
+            len += n;
+        } while (n > 0);
+        buf.rewind();
+        byte[] readData = new byte[len + 1];
+        buf.get(readData);
+        final byte[] expectedData = new byte[len + 1];
+        System.arraycopy(data, 0, expectedData, 0, len + 1);
+        Assert.assertArrayEquals(readData, expectedData);
     }
 
     private void prepareData() throws IOException {
@@ -270,6 +536,43 @@ public abstract class AbstractCipherStreamTest {
         }
         encData = baos.toByteArray();
     }
+    
+    private void doByteBufferWrite(CryptoOutputStream out, boolean 
withChannel) throws Exception {
+        ByteBuffer buf = ByteBuffer.allocateDirect(dataLen / 2);
+        buf.put(data, 0, dataLen / 2);
+        buf.flip();
+        final int n1 = out.write(buf);
+
+        buf.clear();
+        buf.put(data, n1, dataLen / 3);
+        buf.flip();
+        final int n2 = out.write(buf);
+
+        buf.clear();
+        buf.put(data, n1 + n2, dataLen - n1 - n2 - 1);
+        buf.flip();
+        final int n3 = out.write(buf);
+        
+        out.write(1);
+
+        Assert.assertEquals(dataLen, n1 + n2 + n3 + 1);
+        
+        try {
+            out.write(data, 0, data.length + 1);
+            Assert.fail("Expected IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException ex) {
+            Assert.assertNotNull(ex);
+        }
+        
+        out.flush();
+
+        try (InputStream in = getCryptoInputStream(
+                new ByteArrayInputStream(encData), out.getCipher(),
+                defaultBufferSize, iv, withChannel)) {
+            buf = ByteBuffer.allocate(dataLen + 100);
+            byteBufferReadCheck(in, buf, 0);
+        }
+    }
 
     protected CryptoInputStream getCryptoInputStream(final 
ByteArrayInputStream bais,
             final CryptoCipher cipher, final int bufferSize, final byte[] iv, 
final boolean withChannel)
@@ -282,6 +585,24 @@ public abstract class AbstractCipherStreamTest {
         return new CryptoInputStream(bais, cipher, bufferSize,
                 new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
     }
+    
+    protected CryptoInputStream getCryptoInputStream(final String 
transformation, final Properties props, 
+           final ByteArrayInputStream bais, final byte[] key, final 
AlgorithmParameterSpec params,
+           boolean withChannel) throws IOException {
+        if (withChannel) {
+           return new CryptoInputStream(transformation, props, 
Channels.newChannel(bais), new SecretKeySpec(key, "AES"), params);
+       }
+        return new CryptoInputStream(transformation, props, bais, new 
SecretKeySpec(key, "AES"), params);
+    }
+    
+    protected CryptoInputStream getCryptoInputStream(final String 
transformation,
+            final Properties props, final ByteArrayInputStream bais, final Key 
key,
+            final AlgorithmParameterSpec params, boolean withChannel) throws 
IOException {
+        if (withChannel) {
+            return new CryptoInputStream(transformation, props, 
Channels.newChannel(bais), key, params);
+        }
+        return new CryptoInputStream(transformation, props, bais, key, params);
+    }
 
     protected CryptoOutputStream getCryptoOutputStream(
             final ByteArrayOutputStream baos, final CryptoCipher cipher, final 
int bufferSize,
@@ -294,6 +615,26 @@ public abstract class AbstractCipherStreamTest {
         return new CryptoOutputStream(baos, cipher, bufferSize,
                 new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
     }
+    
+    protected CryptoOutputStream getCryptoOutputStream(final String 
transformation,
+            final Properties props, final ByteArrayOutputStream baos, final 
byte[] key, 
+            final AlgorithmParameterSpec param, final boolean withChannel) 
throws IOException {
+        if (withChannel) {
+            return new CryptoOutputStream(transformation, props, 
Channels.newChannel(baos), 
+                    new SecretKeySpec(key, "AES"), param);
+        }
+        return new CryptoOutputStream(transformation, props, baos, new 
SecretKeySpec(key, "AES"), 
+                param);
+    }
+    
+    protected CryptoOutputStream getCryptoOutputStream(final String 
transformation,
+            final Properties props, final ByteArrayOutputStream baos, final 
Key key,
+            final AlgorithmParameterSpec params, boolean withChannel) throws 
IOException {
+        if (withChannel) {
+            return new CryptoOutputStream(transformation, props, 
Channels.newChannel(baos), key, params);
+        }
+        return new CryptoOutputStream(transformation, props, baos, key, 
params);
+    }
 
     private int readAll(final InputStream in, final byte[] b, final int 
offset, final int len)
             throws IOException {
diff --git 
a/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java 
b/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java
index a2ee57d..22e16e9 100644
--- a/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java
+++ b/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java
@@ -20,9 +20,21 @@ package org.apache.commons.crypto.stream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Properties;
 
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import org.apache.commons.crypto.Crypto;
+import org.apache.commons.crypto.cipher.AbstractCipherTest;
 import org.apache.commons.crypto.cipher.CryptoCipher;
+import org.apache.commons.crypto.stream.input.ChannelInput;
+import org.apache.commons.crypto.stream.input.StreamInput;
+import org.apache.commons.crypto.stream.output.ChannelOutput;
+import org.junit.Assert;
+import org.junit.Test;
 
 public class CtrCryptoStreamTest extends AbstractCipherStreamTest {
 
@@ -41,6 +53,17 @@ public class CtrCryptoStreamTest extends 
AbstractCipherStreamTest {
         }
         return new CtrCryptoInputStream(bais, cipher, bufferSize, key, iv);
     }
+    
+    @Override
+    protected CtrCryptoInputStream getCryptoInputStream(final String 
transformation, final Properties props, 
+            final ByteArrayInputStream bais, final byte[] key, final 
AlgorithmParameterSpec params,
+            boolean withChannel) throws IOException {
+        if (withChannel) {
+            return new CtrCryptoInputStream(props, Channels.newChannel(bais), 
key, 
+                    ((IvParameterSpec)params).getIV());
+        }
+        return new CtrCryptoInputStream(props, bais, key, 
((IvParameterSpec)params).getIV());
+    }
 
     @Override
     protected CtrCryptoOutputStream getCryptoOutputStream(
@@ -52,4 +75,115 @@ public class CtrCryptoStreamTest extends 
AbstractCipherStreamTest {
         }
         return new CtrCryptoOutputStream(baos, cipher, bufferSize, key, iv);
     }
+    
+    @Override
+    protected CtrCryptoOutputStream getCryptoOutputStream(final String 
transformation,
+            final Properties props, final ByteArrayOutputStream baos, final 
byte[] key, 
+            final AlgorithmParameterSpec params, final boolean withChannel) 
throws IOException {
+        if (withChannel) {
+            return new CtrCryptoOutputStream(props, Channels.newChannel(baos), 
key, 
+                    ((IvParameterSpec)params).getIV());
+        }
+        return new CtrCryptoOutputStream(props, baos, key, 
((IvParameterSpec)params).getIV());
+    }
+    
+    @Override
+    protected void doFieldGetterTest(final String cipherClass, final 
ByteArrayOutputStream baos,
+            final boolean withChannel) throws Exception {
+        if (AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME.equals(cipherClass)) {
+            if (!Crypto.isNativeCodeLoaded()) {
+                return; // Skip this test if no JNI
+            }
+        }
+        
+        StreamInput streamInput = new StreamInput(new 
ByteArrayInputStream(encData), 0);
+        try {
+            streamInput.seek(0);
+            Assert.fail("Expected UnsupportedOperationException.");
+        } catch (UnsupportedOperationException ex) {
+               Assert.assertEquals(ex.getMessage(), "Seek is not supported by 
this implementation");
+        }
+        try {
+            streamInput.read(0, new byte[0], 0, 0);
+            Assert.fail("Expected UnsupportedOperationException.");
+        } catch (UnsupportedOperationException ex) {
+            Assert.assertEquals(ex.getMessage(), "Positioned read is not 
supported by this implementation");
+        }
+        Assert.assertEquals(streamInput.available(), encData.length);
+        
+        ChannelInput channelInput = new ChannelInput(Channels.newChannel(new 
ByteArrayInputStream(encData)));
+        try {
+            channelInput.seek(0);
+            Assert.fail("Expected UnsupportedOperationException.");
+        } catch (UnsupportedOperationException ex) {
+            Assert.assertEquals(ex.getMessage(), "Seek is not supported by 
this implementation");
+        }
+        try {
+            channelInput.read(0, new byte[0], 0, 0);
+            Assert.fail("Expected UnsupportedOperationException.");
+        } catch (UnsupportedOperationException ex) {
+            Assert.assertEquals(ex.getMessage(), "Positioned read is not 
supported by this implementation");
+        }
+        Assert.assertEquals(channelInput.available(), 0);
+        
+        CtrCryptoInputStream in = new CtrCryptoInputStream(channelInput, 
getCipher(cipherClass), 
+                defaultBufferSize, key, iv);
+        
+        Properties props = new Properties();
+        String bufferSize = "4096";
+        props.put(CryptoInputStream.STREAM_BUFFER_SIZE_KEY, bufferSize);
+        in.setStreamOffset(smallBufferSize);
+       
+        Assert.assertEquals(CryptoInputStream.getBufferSize(props), 
Integer.parseInt(bufferSize));
+        Assert.assertEquals(smallBufferSize, in.getStreamOffset());
+        Assert.assertEquals(in.getBufferSize(), 8192);
+        Assert.assertEquals(in.getCipher().getClass(), 
Class.forName(cipherClass));
+        Assert.assertEquals(in.getKey().getAlgorithm(), "AES");
+        Assert.assertEquals(in.getParams().getClass(), IvParameterSpec.class);
+        Assert.assertNotNull(in.getInput());
+       
+        in.close();
+       
+        CtrCryptoOutputStream out = new CtrCryptoOutputStream(new 
ChannelOutput(
+                Channels.newChannel(baos)), getCipher(cipherClass), 
+                Integer.parseInt(bufferSize), key, iv);
+        out.setStreamOffset(smallBufferSize);
+        Assert.assertEquals(out.getStreamOffset(), smallBufferSize);
+        
+        out.close();
+    }
+    
+    @Test(timeout = 120000)
+    public void testDecrypt() throws Exception {
+        doDecryptTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, false);
+        doDecryptTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, false);
+
+        doDecryptTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, true);
+        doDecryptTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, true);
+    }
+    
+    protected void doDecryptTest(final String cipherClass, final boolean 
withChannel)
+            throws IOException {
+       
+        CtrCryptoInputStream in = getCryptoInputStream(new 
ByteArrayInputStream(encData), 
+                getCipher(cipherClass), defaultBufferSize, iv, withChannel);
+       
+        ByteBuffer buf = ByteBuffer.allocateDirect(dataLen);
+        buf.put(encData);
+        buf.rewind();
+        in.decrypt(buf, 0, dataLen);
+        byte[] readData = new byte[dataLen];
+        byte[] expectedData = new byte[dataLen];
+        buf.get(readData);
+        System.arraycopy(data, 0, expectedData, 0, dataLen);
+        Assert.assertArrayEquals(readData, expectedData);
+        
+        try {
+            in.decryptBuffer(buf);
+            Assert.fail("Expected IOException.");
+        } catch (IOException ex) {
+            Assert.assertEquals(ex.getCause().getClass(), 
ShortBufferException.class); 
+        }
+        
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/crypto/stream/PositionedCryptoInputStreamTest.java
 
b/src/test/java/org/apache/commons/crypto/stream/PositionedCryptoInputStreamTest.java
index 52b9d2e..6293720 100644
--- 
a/src/test/java/org/apache/commons/crypto/stream/PositionedCryptoInputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/crypto/stream/PositionedCryptoInputStreamTest.java
@@ -93,6 +93,12 @@ public class PositionedCryptoInputStreamTest {
                 Arrays.copyOf(encData, encData.length)), cipher, bufferSize,
                 key, iv, 0);
     }
+    
+    private PositionedCryptoInputStream getCryptoInputStream(final int 
streamOffset) 
+            throws IOException {
+        return new PositionedCryptoInputStream(props, new 
PositionedInputForTest(
+                Arrays.copyOf(encData, encData.length)), key, iv, 
streamOffset);
+    }
 
     @Test
     public void doTestJCE() throws Exception {
@@ -107,9 +113,13 @@ public class PositionedCryptoInputStreamTest {
 
     protected void testCipher(final String cipherClass) throws Exception {
         doPositionedReadTests(cipherClass);
+        doPositionedReadTests();
         doReadFullyTests(cipherClass);
+        doReadFullyTests();
         doSeekTests(cipherClass);
+        doSeekTests();
         doMultipleReadTest(cipherClass);
+        doMultipleReadTest();
     }
 
     // when there are multiple positioned read actions and one read action,
@@ -144,6 +154,12 @@ public class PositionedCryptoInputStreamTest {
             }
         }
     }
+    
+    private void doMultipleReadTest() throws Exception{
+        PositionedCryptoInputStream in = getCryptoInputStream(0);
+        final String cipherClass = in.getCipher().getClass().getName();
+        doMultipleReadTest(cipherClass);
+    }
 
     private void doPositionedReadTests(final String cipherClass) throws 
Exception {
         // test with different bufferSize when position = 0
@@ -161,6 +177,12 @@ public class PositionedCryptoInputStreamTest {
         testPositionedReadNone(cipherClass, -1, length, bufferSize);
         testPositionedReadNone(cipherClass, dataLen, length, bufferSize);
     }
+    
+    private void doPositionedReadTests() throws Exception {
+       PositionedCryptoInputStream in = getCryptoInputStream(0);
+       final String cipherClass = in.getCipher().getClass().getName();
+       doPositionedReadTests(cipherClass);
+    }
 
     private void doReadFullyTests(final String cipherClass) throws Exception {
         // test with different bufferSize when position = 0
@@ -177,6 +199,12 @@ public class PositionedCryptoInputStreamTest {
         testReadFullyFailed(cipherClass, dataLen - length + 1, length,
                 bufferSize);
     }
+    
+    private void doReadFullyTests() throws Exception {
+        PositionedCryptoInputStream in = getCryptoInputStream(0);
+        final String cipherClass = in.getCipher().getClass().getName();
+        doReadFullyTests(cipherClass);
+    }
 
     private void doSeekTests(final String cipherClass) throws Exception {
         // test with different length when position = 0
@@ -188,6 +216,12 @@ public class PositionedCryptoInputStreamTest {
         // test exception when position = -1
         testSeekFailed(cipherClass, -1, bufferSize);
     }
+    
+    private void doSeekTests() throws Exception{
+        PositionedCryptoInputStream in = getCryptoInputStream(0);
+        final String cipherClass = in.getCipher().getClass().getName();
+        doSeekTests(cipherClass);
+    }
 
     private void testSeekLoop(final String cipherClass, int position, final 
int length,
             final int bufferSize) throws Exception {
@@ -254,7 +288,7 @@ public class PositionedCryptoInputStreamTest {
             // do the position read full until remain < length
             while (position + length <= total) {
                 final byte[] bytes = new byte[length];
-                in.readFully(position, bytes, 0, length);
+                in.readFully(position, bytes);
                 compareByteArray(testData, position, bytes, length);
                 position += length;
             }
@@ -275,6 +309,7 @@ public class PositionedCryptoInputStreamTest {
             // excepted exception
         }
         in.close();
+        in.close(); // Don't throw exception.
     }
 
     // compare the data from pos with length and data2 from 0 with length

Reply via email to