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

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 464c8aa3be Unit tests
464c8aa3be is described below

commit 464c8aa3be2e20faf6a20c1c7fd03584a2aed662
Author: James Bognar <[email protected]>
AuthorDate: Mon Dec 1 19:02:52 2025 -0800

    Unit tests
---
 .../apache/juneau/commons/utils/StringUtils.java   | 176 ++++++++++-----------
 .../docs/topics/07.01.00.JuneauBctBasics.md        |  14 +-
 juneau-docs/docs/topics/07.01.02.Listifiers.md     |   8 +-
 juneau-docs/docs/topics/07.01.03.Swappers.md       |  12 +-
 .../docs/topics/07.01.04.PropertyExtractors.md     |  20 +--
 5 files changed, 108 insertions(+), 122 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/StringUtils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/StringUtils.java
index c893bc9dae..2c268a2135 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/StringUtils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/StringUtils.java
@@ -51,107 +51,93 @@ import org.apache.juneau.commons.reflect.*;
  */
 public class StringUtils {
 
-       /**
-        * Predicate check to filter out null and empty strings.
-        */
-       public static final Predicate<String> NOT_EMPTY = Utils::isNotEmpty;
+       /** Characters considered common separators 
(comma/semicolon/colon/pipe/tab). */
+       public static final AsciiSet COMMON_SEPARATORS = AsciiSet.of(",;:|\t");
 
-       /**
-        * Empty string constant.
-        */
+       /** Windows-style carriage-return/line-feed sequence. */
+       public static final String CRLF = "\r\n";
+
+       /** Digits 0-9 represented as an {@link AsciiSet}. */
+       public static final AsciiSet DECIMAL_CHARS = AsciiSet.of("0123456789");
+
+       /** Zero-length string constant. */
        public static final String EMPTY = "";
 
-       /**
-        * Single space constant.
-        */
-       public static final String SPACE = " ";
+       /** Characters allowed at the beginning of a numeric literal. */
+       public static final AsciiSet FIRST_NUMBER_CHARS = 
AsciiSet.of("+-.#0123456789");
 
-       /**
-        * Newline constant (line feed character).
-        */
+       /** Hexadecimal digit characters. */
+       public static final AsciiSet HEXADECIMAL_CHARS = 
AsciiSet.of("0123456789abcdefABCDEF");
+
+       /** Characters allowed in HTTP headers (including quoted strings and 
comments). */
+       public static final AsciiSet HTTP_HEADER_CHARS = 
AsciiSet.create().chars("\t -").ranges("!-[","]-}").build();
+
+       /** Characters escaped when parsing key/value pairs. */
+       public static final AsciiSet MAP_ESCAPE_SET = AsciiSet.of(",=\\");
+
+       /** Unix-style newline character. */
        public static final String NEWLINE = "\n";
 
-       /**
-        * Tab constant.
-        */
-       public static final String TAB = "\t";
+       /** Predicate that filters out {@code null} and empty strings. */
+       public static final Predicate<String> NOT_EMPTY = Utils::isNotEmpty;
 
-       /**
-        * Carriage return + line feed constant (Windows line ending).
-        */
-       public static final String CRLF = "\r\n";
+       /** Characters that can appear anywhere in a numeric literal. */
+       public static final AsciiSet NUMBER_CHARS = 
AsciiSet.of("-xX.+-#pP0123456789abcdefABCDEF");
 
-       /**
-        * Common separator characters constant.
-        *
-        * <p>
-        * Contains commonly used separator characters: comma, semicolon, 
colon, pipe, and tab.
-        */
-       public static final String COMMON_SEPARATORS = ",;:|" + TAB;
+       /** Octal digit characters. */
+       public static final AsciiSet OCTAL_CHARS = AsciiSet.of("01234567");
 
-       /**
-        * All whitespace characters constant.
-        *
-        * <p>
-        * Contains all standard whitespace characters: space, tab, newline, 
carriage return, form feed, and vertical tab.
-        */
-       public static final String WHITESPACE_CHARS = " \t\n\r\f\u000B";
+       /** Characters escaped when parsing quoted strings. */
+       public static final AsciiSet QUOTE_ESCAPE_SET = AsciiSet.of("\"'\\");
 
-       private static final AsciiSet numberChars = 
AsciiSet.of("-xX.+-#pP0123456789abcdefABCDEF");
+       /** Single-space character constant. */
+       public static final String SPACE = " ";
 
-       private static final AsciiSet firstNumberChars = 
AsciiSet.of("+-.#0123456789");
-       private static final AsciiSet octChars = AsciiSet.of("01234567");
-       private static final AsciiSet decChars = AsciiSet.of("0123456789");
-       private static final AsciiSet hexChars = 
AsciiSet.of("0123456789abcdefABCDEF");
-       // Maps 6-bit nibbles to BASE64 characters.
-       private static final char[] base64m1 = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
+       /** Horizontal tab character constant. */
+       public static final String TAB = "\t";
+
+       /** Characters considered part of a URI when encoding paths. */
+       public static final AsciiSet URI_CHARS = 
AsciiSet.create().chars("?#+%;/:@&=+$,-_.!~*'()").range('0', '9').range('A', 
'Z').range('a', 'z').build();
+
+       /** Characters that may appear unescaped in path segments when 
URL-encoding. */
+       public static final AsciiSet URL_ENCODE_PATHINFO_VALIDCHARS = 
AsciiSet.create().ranges("a-z", "A-Z", "0-9").chars("-_.*/()").build();
 
-       // Characters that do not need to be URL-encoded
-       private static final AsciiSet unencodedChars = 
AsciiSet.create().ranges("a-z", "A-Z", "0-9").chars("-_.!~*'()\\").build();
+       /** Characters that never require URL encoding per RFC 3986. */
+       public static final AsciiSet URL_UNENCODED_CHARS = 
AsciiSet.create().ranges("a-z", "A-Z", "0-9").chars("-_.!~*'()\\").build();
 
-       // Characters that really do not need to be URL-encoded
-       private static final AsciiSet unencodedCharsLax = 
unencodedChars.copy().chars(":@$,")  // reserved, but can't be confused in a 
query parameter.
-               .chars("{}|\\^[]`")  // unwise characters.
-               .build();
+       /** Extended set of characters that are typically safe to leave 
unencoded. */
+       public static final AsciiSet URL_UNENCODED_LAX_CHARS = 
URL_UNENCODED_CHARS.copy().chars(":@$,").chars("{}|\\^[]`").build();
+
+       /**
+        * All standard whitespace characters (space, tab, newline, carriage 
return, form feed, vertical tab).
+        */
+       public static final AsciiSet WHITESPACE_CHARS = AsciiSet.of(" 
\t\n\r\f\u000B");
 
-       // Valid HTTP header characters (including quoted strings and comments).
-       // @formatter:off
-       private static final AsciiSet httpHeaderChars = AsciiSet
-               .create()
-               .chars("\t -")
-               .ranges("!-[","]-}")
-               .build();
-       // @formatter:on
+       // Maps 6-bit nibbles to BASE64 characters.
+       private static final char[] BASE64M1 = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
 
        // Maps BASE64 characters to 6-bit nibbles.
-       private static final byte[] base64m2 = new byte[128];
+       private static final byte[] BASE64M2 = new byte[128];
 
        static {
                for (var i = 0; i < 64; i++)
-                       base64m2[base64m1[i]] = (byte)i;
+                       BASE64M2[BASE64M1[i]] = (byte)i;
        }
        private static final Random RANDOM = new Random();
 
-       private static final Pattern fpRegex = Pattern.compile(
+       private static final Pattern FP_REGEX = Pattern.compile(
                
"[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*"
  // NOSONAR
        );
 
        static final Map<Character,AsciiSet> ESCAPE_SETS = new 
ConcurrentHashMap<>();
 
-       static final AsciiSet MAP_ESCAPE_SET = AsciiSet.of(",=\\");
-
-       static final AsciiSet QUOTE_ESCAPE_SET = AsciiSet.of("\"'\\");
-
-       private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
+       private static final char[] HEX_ARRAY = 
"0123456789ABCDEF".toCharArray();
 
        private static final List<Tuple2<Class<?>,Function<Object,String>>> 
READIFIERS = loadReadifiers();
        private static final Cache<Class<?>,Function<Object,String>> 
READIFIER_CACHE = Cache.<Class<?>,Function<Object,String>>create().build();
 
        private static final char[] HEX = "0123456789ABCDEF".toCharArray();
 
-       private static final AsciiSet URL_ENCODE_PATHINFO_VALIDCHARS = 
AsciiSet.create().ranges("a-z", "A-Z", "0-9").chars("-_.*/()").build();
-       private static final AsciiSet URI_CHARS = 
AsciiSet.create().chars("?#+%;/:@&=+$,-_.!~*'()").range('0', '9').range('A', 
'Z').range('a', 'z').build();
-
        /**
         * Abbreviates a string using ellipses if it exceeds the specified 
length.
         *
@@ -344,10 +330,10 @@ public class StringUtils {
                        var i1 = bIn[iIn++];
                        var i2 = iIn < inLength ? bIn[iIn++] : 'A';
                        var i3 = iIn < inLength ? bIn[iIn++] : 'A';
-                       var b0 = base64m2[i0];
-                       var b1 = base64m2[i1];
-                       var b2 = base64m2[i2];
-                       var b3 = base64m2[i3];
+                       var b0 = BASE64M2[i0];
+                       var b1 = BASE64M2[i1];
+                       var b2 = BASE64M2[i2];
+                       var b3 = BASE64M2[i3];
                        var o0 = (b0 << 2) | (b1 >>> 4);
                        var o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
                        var o2 = ((b2 & 3) << 6) | b3;
@@ -394,11 +380,11 @@ public class StringUtils {
                        var o1 = ((i0 & 3) << 4) | (i1 >>> 4);
                        var o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
                        var o3 = i2 & 0x3F;
-                       out[iOut++] = base64m1[o0];
-                       out[iOut++] = base64m1[o1];
-                       out[iOut] = iOut < outLength ? base64m1[o2] : '=';
+                       out[iOut++] = BASE64M1[o0];
+                       out[iOut++] = BASE64M1[o1];
+                       out[iOut] = iOut < outLength ? BASE64M1[o2] : '=';
                        iOut++;
-                       out[iOut] = iOut < outLength ? base64m1[o3] : '=';
+                       out[iOut] = iOut < outLength ? BASE64M1[o3] : '=';
                        iOut++;
                }
                return new String(out);
@@ -3116,7 +3102,7 @@ public class StringUtils {
         * @return <jk>true</jk> if the specified string is numeric.
         */
        public static boolean isDecimal(String s) {
-               if (s == null || s.isEmpty() || ! 
firstNumberChars.contains(s.charAt(0)))
+               if (s == null || s.isEmpty() || ! 
FIRST_NUMBER_CHARS.contains(s.charAt(0)))
                        return false;
                var i = 0;
                var length = s.length();
@@ -3133,24 +3119,24 @@ public class StringUtils {
                        c = s.charAt(i++);
                        if (c == 'x' || c == 'X') {
                                for (var j = i; j < length; j++) {
-                                       if (! hexChars.contains(s.charAt(j)))
+                                       if (! 
HEXADECIMAL_CHARS.contains(s.charAt(j)))
                                                return false;
                                }
-                       } else if (octChars.contains(c)) {
+                       } else if (OCTAL_CHARS.contains(c)) {
                                for (var j = i; j < length; j++)
-                                       if (! octChars.contains(s.charAt(j)))
+                                       if (! OCTAL_CHARS.contains(s.charAt(j)))
                                                return false;
                        } else {
                                return false;
                        }
                } else if (c == '#') {
                        for (var j = i; j < length; j++) {
-                               if (! hexChars.contains(s.charAt(j)))
+                               if (! HEXADECIMAL_CHARS.contains(s.charAt(j)))
                                        return false;
                        }
-               } else if (decChars.contains(c)) {
+               } else if (DECIMAL_CHARS.contains(c)) {
                        for (var j = i; j < length; j++)
-                               if (! decChars.contains(s.charAt(j)))
+                               if (! DECIMAL_CHARS.contains(s.charAt(j)))
                                        return false;
                } else {
                        return false;
@@ -3234,7 +3220,7 @@ public class StringUtils {
         * @return <jk>true</jk> if the specified character is a valid first 
character for a number.
         */
        public static boolean isFirstNumberChar(char c) {
-               return firstNumberChars.contains(c);
+               return FIRST_NUMBER_CHARS.contains(c);
        }
 
        /**
@@ -3246,7 +3232,7 @@ public class StringUtils {
        public static boolean isFloat(String s) {
                if (s == null || s.isEmpty())
                        return false;
-               if (! firstNumberChars.contains(s.charAt(0)))
+               if (! FIRST_NUMBER_CHARS.contains(s.charAt(0)))
                        return (s.equals("NaN") || s.equals("Infinity"));
                var i = 0;
                var length = s.length();
@@ -3256,8 +3242,8 @@ public class StringUtils {
                if (i == length)
                        return false;
                c = s.charAt(i);
-               if (c == '.' || decChars.contains(c)) {
-                       return fpRegex.matcher(s).matches();
+               if (c == '.' || DECIMAL_CHARS.contains(c)) {
+                       return FP_REGEX.matcher(s).matches();
                }
                return false;
        }
@@ -3381,7 +3367,7 @@ public class StringUtils {
         * @return <jk>true</jk> if the specified character is a valid number 
character.
         */
        public static boolean isNumberChar(char c) {
-               return numberChars.contains(c);
+               return NUMBER_CHARS.contains(c);
        }
 
        /**
@@ -6961,7 +6947,7 @@ public class StringUtils {
 
                var needsReplace = false;
                for (var i = 0; i < s.length() && ! needsReplace; i++)
-                       needsReplace |= httpHeaderChars.contains(s.charAt(i));
+                       needsReplace |= HTTP_HEADER_CHARS.contains(s.charAt(i));
 
                if (! needsReplace)
                        return s;
@@ -6969,7 +6955,7 @@ public class StringUtils {
                var sb = new StringBuilder(s.length());
                for (var i = 0; i < s.length(); i++) {
                        var c = s.charAt(i);
-                       if (httpHeaderChars.contains(c))
+                       if (HTTP_HEADER_CHARS.contains(c))
                                sb.append(c);
                }
 
@@ -7158,8 +7144,8 @@ public class StringUtils {
        public static String toHex(byte b) {
                var c = new char[2];
                var v = b & 0xFF;
-               c[0] = hexArray[v >>> 4];
-               c[1] = hexArray[v & 0x0F];
+               c[0] = HEX_ARRAY[v >>> 4];
+               c[1] = HEX_ARRAY[v & 0x0F];
                return new String(c);
        }
 
@@ -7713,7 +7699,7 @@ public class StringUtils {
                var needsEncode = false;
 
                for (var i = 0; i < s.length() && ! needsEncode; i++)
-                       needsEncode |= (! unencodedChars.contains(s.charAt(i)));
+                       needsEncode |= (! 
URL_UNENCODED_CHARS.contains(s.charAt(i)));
 
                if (needsEncode) {
                        try {
@@ -7735,12 +7721,12 @@ public class StringUtils {
                        return null;
                var needsEncode = false;
                for (var i = 0; i < s.length() && ! needsEncode; i++)
-                       needsEncode |= (! 
unencodedCharsLax.contains(s.charAt(i)));
+                       needsEncode |= (! 
URL_UNENCODED_LAX_CHARS.contains(s.charAt(i)));
                if (needsEncode) {
                        var sb = new StringBuilder(s.length() * 2);
                        for (var i = 0; i < s.length(); i++) {
                                var c = s.charAt(i);
-                               if (unencodedCharsLax.contains(c))
+                               if (URL_UNENCODED_LAX_CHARS.contains(c))
                                        sb.append(c);
                                else if (c == ' ')
                                        sb.append("+");
diff --git a/juneau-docs/docs/topics/07.01.00.JuneauBctBasics.md 
b/juneau-docs/docs/topics/07.01.00.JuneauBctBasics.md
index 6a4ee71d69..e8187f5ae2 100644
--- a/juneau-docs/docs/topics/07.01.00.JuneauBctBasics.md
+++ b/juneau-docs/docs/topics/07.01.00.JuneauBctBasics.md
@@ -544,13 +544,13 @@ The default bean converter can be customized on a 
per-thread basis using `setCon
 // Set custom converter in @BeforeEach method
 @BeforeEach
 void setUp() {
-    var converter = BasicBeanConverter.builder()
-        .defaultSettings()
-        .addStringifier(LocalDate.class, date -> 
-            date.format(DateTimeFormatter.ISO_LOCAL_DATE))
-        .addStringifier(Money.class, money -> 
-            money.getAmount().toPlainString())
-        .build();
+var converter = BasicBeanConverter.builder()
+    .defaultSettings()
+    .addStringifier(LocalDate.class, date -> 
+        date.format(DateTimeFormatter.ISO_LOCAL_DATE))
+    .addStringifier(Money.class, money -> 
+        money.getAmount().toPlainString())
+    .build();
     BctAssertions.setConverter(converter);
 }
 
diff --git a/juneau-docs/docs/topics/07.01.02.Listifiers.md 
b/juneau-docs/docs/topics/07.01.02.Listifiers.md
index 44b3de4c1b..6f9de86b2d 100644
--- a/juneau-docs/docs/topics/07.01.02.Listifiers.md
+++ b/juneau-docs/docs/topics/07.01.02.Listifiers.md
@@ -159,8 +159,8 @@ ResultSet rs = statement.executeQuery("SELECT name FROM 
users");
 BctAssertions.setConverter(converter);
 try {
     assertList(rs, 
-              predicate(row -> ((Map)row).get("name").equals("Alice")),
-              predicate(row -> ((Map)row).get("name").equals("Bob")));
+          predicate(row -> ((Map)row).get("name").equals("Alice")),
+          predicate(row -> ((Map)row).get("name").equals("Bob")));
 } finally {
     BctAssertions.resetConverter();
 }
@@ -173,8 +173,8 @@ try {
 BctAssertions.setConverter(converter);
 try {
     assertBean(paginatedResult, 
-              "items{#{name}},totalCount", 
-              "[{Alice},{Bob},{Charlie}],3");
+          "items{#{name}},totalCount", 
+          "[{Alice},{Bob},{Charlie}],3");
 } finally {
     BctAssertions.resetConverter();
 }
diff --git a/juneau-docs/docs/topics/07.01.03.Swappers.md 
b/juneau-docs/docs/topics/07.01.03.Swappers.md
index b18be8cb73..ee060bd61b 100644
--- a/juneau-docs/docs/topics/07.01.03.Swappers.md
+++ b/juneau-docs/docs/topics/07.01.03.Swappers.md
@@ -182,13 +182,13 @@ Result<User> result = userService.createUser(userData);
 BctAssertions.setConverter(converter);
 try {
     assertBean(result, "name,email", "Alice,[email protected]");
-    
-    // Test validation results
-    ValidationResult<Order> validation = orderValidator.validate(order);
+
+// Test validation results
+ValidationResult<Order> validation = orderValidator.validate(order);
     assertBean(validation, "id,total", "123,99.99");
-    
-    // Test error case
-    ValidationResult<Order> invalidValidation = 
orderValidator.validate(invalidOrder);
+
+// Test error case
+ValidationResult<Order> invalidValidation = 
orderValidator.validate(invalidOrder);
     assertList(invalidValidation, "Missing required field: customer", "Invalid 
total: -10");
 } finally {
     BctAssertions.resetConverter();
diff --git a/juneau-docs/docs/topics/07.01.04.PropertyExtractors.md 
b/juneau-docs/docs/topics/07.01.04.PropertyExtractors.md
index 4245e4423c..4f24da3162 100644
--- a/juneau-docs/docs/topics/07.01.04.PropertyExtractors.md
+++ b/juneau-docs/docs/topics/07.01.04.PropertyExtractors.md
@@ -155,7 +155,7 @@ PropertyExtractor computedExtractor = new 
PropertyExtractor() {
 BctAssertions.setConverter(converter);
 try {
     assertBean(user, "computed_fullName,computed_age,computed_initials", 
-              "John Doe,30,J.D.");
+          "John Doe,30,J.D.");
 } finally {
     BctAssertions.resetConverter();
 }
@@ -280,7 +280,7 @@ PropertyExtractor configExtractor = new PropertyExtractor() 
{
 BctAssertions.setConverter(converter);
 try {
     assertBean(config, "database.host,database.port,app.name", 
-              "localhost,5432,MyApp");
+          "localhost,5432,MyApp");
 } finally {
     BctAssertions.resetConverter();
 }
@@ -451,14 +451,14 @@ DatabaseEntity entity = loadEntity(123);
 BctAssertions.setConverter(converter);
 try {
     assertBean(entity, "id,displayName,createdDate", "123,John 
Doe,2023-01-15");
-    
-    // Test configuration
-    Configuration config = loadConfig();
+
+// Test configuration
+Configuration config = loadConfig();
     assertBean(config, "database.host,database.port,app.timeout", 
-              "localhost,5432,30000");
-    
-    // Test computed properties
-    User user = loadUser(456);
+          "localhost,5432,30000");
+
+// Test computed properties
+User user = loadUser(456);
     assertBean(user, "computed_fullName,computed_age", "Alice Smith,28");
 } finally {
     BctAssertions.resetConverter();
@@ -472,7 +472,7 @@ try {
 BctAssertions.setConverter(converter);
 try {
     assertBean(order, "customer{computed_fullName},items{0{name}}", 
-              "{John Doe},{{Laptop}}");
+          "{John Doe},{{Laptop}}");
 } finally {
     BctAssertions.resetConverter();
 }

Reply via email to