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

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

commit 3b23d97d94dcc8abdb1c505ab7690bc7db3b316c
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Mon May 27 12:44:37 2024 -0400

    Add more tests
    
    Refactor internals
---
 .../java/org/apache/commons/net/util/Base64.java   |  38 ++++--
 .../org/apache/commons/net/util/Base64Test.java    | 129 ++++++++++++++++-----
 2 files changed, 128 insertions(+), 39 deletions(-)

diff --git a/src/main/java/org/apache/commons/net/util/Base64.java 
b/src/main/java/org/apache/commons/net/util/Base64.java
index 4531bb31..aa1730c4 100644
--- a/src/main/java/org/apache/commons/net/util/Base64.java
+++ b/src/main/java/org/apache/commons/net/util/Base64.java
@@ -19,6 +19,8 @@ package org.apache.commons.net.util;
 
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
+import java.util.Base64.Decoder;
+import java.util.Base64.Encoder;
 import java.util.Objects;
 
 /**
@@ -230,9 +232,15 @@ public class Base64 {
      *
      * @param binaryData binary data to encode
      * @return Base64 characters chunked in 76 character blocks
+     * @throws ArithmeticException if the {@code binaryData} would overflows a 
byte[].
      */
     public static byte[] encodeBase64Chunked(final byte[] binaryData) {
-        return encodeBase64(binaryData, true);
+        final long encodeLength = getEncodeLength(binaryData, CHUNK_SIZE, 
CHUNK_SEPARATOR);
+        final byte[] dst = new byte[Math.toIntExact(encodeLength)];
+        getMimeEncoder().encode(binaryData, dst);
+        dst[dst.length - 2] = CHUNK_SEPARATOR[0];
+        dst[dst.length - 1] = CHUNK_SEPARATOR[1];
+        return dst;
     }
 
     /**
@@ -249,7 +257,7 @@ public class Base64 {
      * @since 1.4
      */
     public static String encodeBase64String(final byte[] binaryData) {
-        return java.util.Base64.getMimeEncoder().encodeToString(binaryData) + 
"\r\n";
+        return getMimeEncoder().encodeToString(binaryData) + "\r\n";
     }
 
     /**
@@ -275,7 +283,7 @@ public class Base64 {
      * @since 3.2
      */
     public static String encodeBase64StringUnChunked(final byte[] binaryData) {
-        return newStringUtf8(encodeBase64(binaryData, false));
+        return getEncoder().encodeToString(binaryData);
     }
 
     /**
@@ -314,19 +322,23 @@ public class Base64 {
         return encodeBase64(toIntegerBytes(bigInt), false);
     }
 
+    private static Decoder getDecoder() {
+        return java.util.Base64.getDecoder();
+    }
+
     /**
      * Pre-calculates the amount of space needed to base64-encode the supplied 
array.
      *
-     * @param pArray         byte[] array which will later be encoded
+     * @param array          byte[] array which will later be encoded
      * @param chunkSize      line-length of the output (<= 0 means no 
chunking) between each chunkSeparator (e.g. CRLF).
      * @param chunkSeparator the sequence of bytes used to separate chunks of 
output (e.g. CRLF).
      *
      * @return amount of space needed to encode the supplied array. Returns a 
long since a max-len array will require Integer.MAX_VALUE + 33%.
      */
-    private static long getEncodeLength(final byte[] pArray, int chunkSize, 
final byte[] chunkSeparator) {
+    static long getEncodeLength(final byte[] array, int chunkSize, final 
byte[] chunkSeparator) {
         // base64 always encodes to multiples of 4.
         chunkSize = chunkSize / 4 * 4;
-        long len = pArray.length * 4 / 3;
+        long len = array.length * 4 / 3;
         final long mod = len % 4;
         if (mod != 0) {
             len += 4 - mod;
@@ -341,6 +353,14 @@ public class Base64 {
         return len;
     }
 
+    private static Encoder getEncoder() {
+        return java.util.Base64.getEncoder();
+    }
+
+    private static Encoder getMimeEncoder() {
+        return java.util.Base64.getMimeEncoder();
+    }
+
     /**
      * Tests a given byte array to see if it contains only valid characters 
within the Base64 alphabet. Currently, the method treats whitespace as valid.
      *
@@ -395,7 +415,7 @@ public class Base64 {
      * @param bigInt <code>BigInteger</code> to be converted
      * @return a byte array representation of the BigInteger parameter
      */
-    static byte[] toIntegerBytes(final BigInteger bigInt) {
+    private static byte[] toIntegerBytes(final BigInteger bigInt) {
         Objects.requireNonNull(bigInt, "bigInt");
         int bitlen = bigInt.bitLength();
         // round bitlen
@@ -611,7 +631,7 @@ public class Base64 {
         if (source == null || source.length == 0) {
             return source;
         }
-        return java.util.Base64.getDecoder().decode(source);
+        return getDecoder().decode(source);
     }
 
     /**
@@ -622,7 +642,7 @@ public class Base64 {
      * @since 1.4
      */
     public byte[] decode(final String source) {
-        return java.util.Base64.getDecoder().decode(source);
+        return getDecoder().decode(source);
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/net/util/Base64Test.java 
b/src/test/java/org/apache/commons/net/util/Base64Test.java
index 475007cf..45588677 100644
--- a/src/test/java/org/apache/commons/net/util/Base64Test.java
+++ b/src/test/java/org/apache/commons/net/util/Base64Test.java
@@ -39,14 +39,14 @@ public class Base64Test {
 
     private void checkDecoders(final String expected, final byte[] actual) {
         final byte[] decoded = Base64.decodeBase64(actual);
-        assertEquals(expected, new String(decoded, StandardCharsets.UTF_8));
+        assertEquals(expected, toString(decoded));
         assertEquals(expected, new String(getJreDecoder().decode(actual), 
StandardCharsets.UTF_8));
     }
 
     private void checkDecoders(final String expected, final String actual) {
         final byte[] decoded = Base64.decodeBase64(actual);
         assertEquals(expected, new String(decoded));
-        assertEquals(expected, new String(decoded, StandardCharsets.UTF_8));
+        assertEquals(expected, toString(decoded));
         assertEquals(expected, new String(getJreDecoder().decode(actual), 
StandardCharsets.UTF_8));
     }
 
@@ -58,6 +58,10 @@ public class Base64Test {
         return java.util.Base64.getEncoder();
     }
 
+    private Encoder getJreMimeEncoder() {
+        return java.util.Base64.getMimeEncoder();
+    }
+
     @Test
     public void testBase64() {
         final Base64 b64 = new Base64();
@@ -135,12 +139,6 @@ public class Base64Test {
         assertEquals(bi, 
Base64.decodeInteger(getJreEncoder().encode(bi.toByteArray())));
     }
 
-    private void testEncodeInteger(final BigInteger bi) {
-        final byte[] decodedBytes = 
getJreDecoder().decode(Base64.encodeInteger(bi));
-        final BigInteger decoded = decodedBytes.length == 0 ? BigInteger.ZERO 
: new BigInteger(decodedBytes);
-        assertEquals(bi, decoded);
-    }
-
     @Test
     public void testDecodeNullString() {
         final Base64 base64 = new Base64();
@@ -152,28 +150,54 @@ public class Base64Test {
         checkDecoders("Hello World!", "SGVsbG8gV29ybGQh");
     }
 
-    @Test
-    public void testEncodeBase64ByteArray() {
-        final byte[] binaryData = null;
-        assertArrayEquals(binaryData, Base64.encodeBase64(binaryData));
-    }
-
     @Test
     public void testEncodeBase64ByteArrayBoolean() {
         final byte[] binaryData = { '1', '2', '3' };
+        final byte[] urlUnsafeData = "<<???>>".getBytes();
+        final byte[] urlUnsafeDataChunky = 
"<<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>>".getBytes();
         byte[] encoded;
+        // Boolean parameter: "isChunked".
+        //
+        // isChunked false
         encoded = Base64.encodeBase64(binaryData, false);
         assertNotNull(encoded);
         assertEquals(4, encoded.length);
+        assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, 
Base64.CHUNK_SEPARATOR) - 2, encoded.length);
+        assertEquals(getJreEncoder().encodeToString(binaryData), 
toString(encoded));
+        assertEquals("MTIz", toString(encoded));
+        // URL unsafe
+        // <<???>>
+        encoded = Base64.encodeBase64(urlUnsafeData, false);
+        assertEquals("PDw/Pz8+Pg==", toString(encoded));
+        encoded = Base64.encodeBase64(urlUnsafeDataChunky, false);
+        assertEquals(getJreEncoder().encodeToString(urlUnsafeDataChunky), 
toString(encoded));
+        //
+        // isChunked false
         encoded = Base64.encodeBase64(binaryData, false);
         assertNotNull(encoded);
         assertEquals(4, encoded.length);
+        assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, 
Base64.CHUNK_SEPARATOR) - 2, encoded.length);
+        assertEquals("MTIz", toString(encoded));
+        //
+        // isChunked true
         encoded = Base64.encodeBase64(binaryData, true);
         assertNotNull(encoded);
         assertEquals(6, encoded.length); // always adds trailer
+        assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, 
Base64.CHUNK_SEPARATOR), encoded.length);
+        assertEquals("MTIz\r\n", toString(encoded));
+        // URL unsafe
+        // <<???>>
+        encoded = Base64.encodeBase64(urlUnsafeData, true);
+        assertEquals("PDw/Pz8+Pg==\r\n", toString(encoded));
+        encoded = Base64.encodeBase64(urlUnsafeDataChunky, true);
+        assertEquals(getJreMimeEncoder().encodeToString(urlUnsafeDataChunky) + 
"\r\n", toString(encoded));
+        //
+        // isChunked true
         encoded = Base64.encodeBase64(binaryData, true);
         assertNotNull(encoded);
         assertEquals(6, encoded.length);
+        assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, 
Base64.CHUNK_SEPARATOR), encoded.length);
+        assertEquals("MTIz\r\n", toString(encoded));
     }
 
     @Test
@@ -214,30 +238,48 @@ public class Base64Test {
         assertEquals(6, encoded.length);
     }
 
+    @Test
+    public void testEncodeBase64ByteArrayEdges() {
+        final byte[] binaryData = null;
+        assertArrayEquals(binaryData, Base64.encodeBase64(binaryData));
+        final byte[] binaryData2 = new byte[0];
+        assertArrayEquals(binaryData2, Base64.encodeBase64(binaryData2));
+    }
+
     @Test
     public void testEncodeBase64Chunked() {
-        final byte[] bytesToEncode = { 'f', 'o', 'o', 'b', 'a', 'r' };
-        final byte[] encodedData = Base64.encodeBase64Chunked(bytesToEncode);
-        assertEquals("Zm9vYmFy\r\n", new String(encodedData, 
StandardCharsets.UTF_8));
+        byte[] bytesToEncode = { 'f', 'o', 'o', 'b', 'a', 'r' };
+        byte[] encodedData = Base64.encodeBase64Chunked(bytesToEncode);
+        assertEquals("Zm9vYmFy\r\n", toString(encodedData));
+        // URL unsafe data
+        // <<???>>
+        bytesToEncode = "<<???>>".getBytes();
+        encodedData = Base64.encodeBase64Chunked(bytesToEncode);
+        assertEquals("PDw/Pz8+Pg==\r\n", toString(encodedData));
         // > 76
         final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], 
(byte) 'A');
         final byte[] chunked = Base64.encodeBase64Chunked(chunkMe);
         assertEquals('\r', chunked[chunked.length - 2]);
         assertEquals('\n', chunked[chunked.length - 1]);
-        
assertArrayEquals(ArrayUtils.addAll(java.util.Base64.getMimeEncoder().encode(chunkMe),
 Base64.CHUNK_SEPARATOR), chunked);
+        
assertArrayEquals(ArrayUtils.addAll(getJreMimeEncoder().encode(chunkMe), 
Base64.CHUNK_SEPARATOR), chunked);
     }
 
     @Test
     public void testEncodeBase64StringByteArray() {
-        final String stringToEncode = "Many hands make light work.";
-        final String encodedData = 
Base64.encodeBase64String(stringToEncode.getBytes());
+        String stringToEncode = "Many hands make light work.";
+        String encodedData = 
Base64.encodeBase64String(stringToEncode.getBytes());
         assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu\r\n", encodedData);
+        // URL unsafe data
+        // <<???>>
+        stringToEncode = "<<???>>";
+        encodedData = Base64.encodeBase64String(stringToEncode.getBytes());
+        assertEquals("PDw/Pz8+Pg==\r\n", encodedData);
         // > 76
         final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], 
(byte) 'A');
         final String chunked = Base64.encodeBase64String(chunkMe);
         assertEquals('\r', chunked.charAt(chunked.length() - 2));
         assertEquals('\n', chunked.charAt(chunked.length() - 1));
-        assertEquals(java.util.Base64.getMimeEncoder().encodeToString(chunkMe) 
+ "\r\n", chunked);
+        assertEquals(getJreMimeEncoder().encodeToString(chunkMe) + "\r\n", 
chunked);
     }
 
     @Test
@@ -251,25 +293,42 @@ public class Base64Test {
 
     @Test
     public void testEncodeBase64StringUnChunked() {
-        final byte[] bytesToEncode = "Many hands make light work.".getBytes();
-        final String encodedData = 
Base64.encodeBase64StringUnChunked(bytesToEncode);
+        byte[] bytesToEncode = "Many hands make light work.".getBytes();
+        String encodedData = Base64.encodeBase64StringUnChunked(bytesToEncode);
         assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", encodedData);
+        // URL unsafe data
+        // <<???>>
+        bytesToEncode = "<<???>>".getBytes();
+        encodedData = Base64.encodeBase64StringUnChunked(bytesToEncode);
+        assertEquals("PDw/Pz8+Pg==", encodedData);
+        // > 76
+        final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], 
(byte) 'A');
+        final String chunked = Base64.encodeBase64StringUnChunked(chunkMe);
+        assertEquals(getJreEncoder().encodeToString(chunkMe), chunked);
     }
 
     @Test
     public void testEncodeBase64URLSafe() {
-        final byte[] bytesToEncode = "Many hands make light work.".getBytes();
-        final byte[] encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
-        assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", new 
String(encodedData, StandardCharsets.UTF_8));
-        // TODO more
+        byte[] bytesToEncode = "Many hands make light work.".getBytes();
+        byte[] encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
+        assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", 
toString(encodedData));
+        // URL unsafe data
+        // <<???>>
+        bytesToEncode = "<<???>>".getBytes();
+        encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
+        assertEquals("PDw_Pz8-Pg", toString(encodedData));
     }
 
     @Test
     public void testEncodeBase64URLSafeString() {
-        final byte[] bytesToEncode = "Many hands make light work.".getBytes();
-        final String encodedData = 
Base64.encodeBase64URLSafeString(bytesToEncode);
+        byte[] bytesToEncode = "Many hands make light work.".getBytes();
+        String encodedData = Base64.encodeBase64URLSafeString(bytesToEncode);
         assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", encodedData);
-        // TODO more
+        // URL unsafe data
+        // <<???>>
+        bytesToEncode = "<<???>>".getBytes();
+        encodedData = Base64.encodeBase64URLSafeString(bytesToEncode);
+        assertEquals("PDw_Pz8-Pg", encodedData);
     }
 
     @Test
@@ -286,6 +345,12 @@ public class Base64Test {
         testEncodeInteger(BigInteger.ZERO);
     }
 
+    private void testEncodeInteger(final BigInteger bi) {
+        final byte[] decodedBytes = 
getJreDecoder().decode(Base64.encodeInteger(bi));
+        final BigInteger decoded = decodedBytes.length == 0 ? BigInteger.ZERO 
: new BigInteger(decodedBytes);
+        assertEquals(bi, decoded);
+    }
+
     @Test
     public void testEncodeToString() {
         final Base64 base64 = new Base64();
@@ -305,4 +370,8 @@ public class Base64Test {
         assertFalse(Base64.isBase64((byte) ' '));
     }
 
+    private String toString(byte[] encodedData) {
+        return new String(encodedData, StandardCharsets.UTF_8);
+    }
+
 }

Reply via email to