Author: sebb Date: Sat Jun 9 15:06:14 2012 New Revision: 1348424 URL: http://svn.apache.org/viewvc?rev=1348424&view=rev Log: LANG-805 RandomStringUtils.random(count, 0, 0, false, false, universe, random) always throws java.lang.ArrayIndexOutOfBoundsException Merge fixes from LANG3 code
Modified: commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/RandomStringUtils.java commons/proper/lang/branches/LANG_2_X/src/site/changes/changes.xml commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/RandomStringUtilsTest.java Modified: commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/RandomStringUtils.java URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/RandomStringUtils.java?rev=1348424&r1=1348423&r2=1348424&view=diff ============================================================================== --- commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/RandomStringUtils.java (original) +++ commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/RandomStringUtils.java Sat Jun 9 15:06:14 2012 @@ -17,10 +17,11 @@ package org.apache.commons.lang; import java.util.Random; + /** - * <p>Operations for random <code>String</code>s.</p> + * <p>Operations for random {@code String}s.</p> * <p>Currently <em>private high surrogate</em> characters are ignored. - * These are unicode characters that fall between the values 56192 (db80) + * These are Unicode characters that fall between the values 56192 (db80) * and 56319 (dbff) as we don't know how to handle them. * High and low surrogates are correctly dealt with - that is if a * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f) @@ -29,10 +30,6 @@ import java.util.Random; * chosen high surrogate. </p> * * <p>#ThreadSafe#</p> - * @author Apache Software Foundation - * @author <a href="mailto:ste...@caswell.name">Steven Caswell</a> - * @author Gary Gregory - * @author Phil Steitz * @since 1.0 * @version $Id$ */ @@ -46,9 +43,9 @@ public class RandomStringUtils { private static final Random RANDOM = new Random(); /** - * <p><code>RandomStringUtils</code> instances should NOT be constructed in + * <p>{@code RandomStringUtils} instances should NOT be constructed in * standard programming. Instead, the class should be used as - * <code>RandomStringUtils.random(5);</code>.</p> + * {@code RandomStringUtils.random(5);}.</p> * * <p>This constructor is public to permit tools that require a JavaBean instance * to operate.</p> @@ -77,7 +74,7 @@ public class RandomStringUtils { * specified.</p> * * <p>Characters will be chosen from the set of characters whose - * ASCII value is between <code>32</code> and <code>126</code> (inclusive).</p> + * ASCII value is between {@code 32} and {@code 126} (inclusive).</p> * * @param count the length of random string to create * @return the random string @@ -136,9 +133,9 @@ public class RandomStringUtils { * characters as indicated by the arguments.</p> * * @param count the length of random string to create - * @param letters if <code>true</code>, generated string will include + * @param letters if {@code true}, generated string will include * alphabetic characters - * @param numbers if <code>true</code>, generated string will include + * @param numbers if {@code true}, generated string will include * numeric characters * @return the random string */ @@ -156,9 +153,9 @@ public class RandomStringUtils { * @param count the length of random string to create * @param start the position in set of chars to start at * @param end the position in set of chars to end before - * @param letters if <code>true</code>, generated string will include + * @param letters if {@code true}, generated string will include * alphabetic characters - * @param numbers if <code>true</code>, generated string will include + * @param numbers if {@code true}, generated string will include * numeric characters * @return the random string */ @@ -181,10 +178,10 @@ public class RandomStringUtils { * @param letters only allow letters? * @param numbers only allow numbers? * @param chars the set of chars to choose randoms from. - * If <code>null</code>, then it will use the set of all chars. + * If {@code null}, then it will use the set of all chars. * @return the random string * @throws ArrayIndexOutOfBoundsException if there are not - * <code>(end - start) + 1</code> characters in the set array. + * {@code (end - start) + 1} characters in the set array. */ public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) { return random(count, start, end, letters, numbers, chars, RANDOM); @@ -194,13 +191,13 @@ public class RandomStringUtils { * <p>Creates a random string based on a variety of options, using * supplied source of randomness.</p> * - * <p>If start and end are both <code>0</code>, start and end are set - * to <code>' '</code> and <code>'z'</code>, the ASCII printable + * <p>If start and end are both {@code 0}, start and end are set + * to {@code ' '} and {@code 'z'}, the ASCII printable * characters, will be used, unless letters and numbers are both - * <code>false</code>, in which case, start and end are set to - * <code>0</code> and <code>Integer.MAX_VALUE</code>. + * {@code false}, in which case, start and end are set to + * {@code 0} and {@code Integer.MAX_VALUE}. * - * <p>If set is not <code>null</code>, characters between start and + * <p>If set is not {@code null}, characters between start and * end are chosen.</p> * * <p>This method accepts a user-supplied {@link Random} @@ -214,13 +211,13 @@ public class RandomStringUtils { * @param end the position in set of chars to end before * @param letters only allow letters? * @param numbers only allow numbers? - * @param chars the set of chars to choose randoms from. - * If <code>null</code>, then it will use the set of all chars. + * @param chars the set of chars to choose randoms from, must not be empty. + * If {@code null}, then it will use the set of all chars. * @param random a source of randomness. * @return the random string * @throws ArrayIndexOutOfBoundsException if there are not - * <code>(end - start) + 1</code> characters in the set array. - * @throws IllegalArgumentException if <code>count</code> < 0. + * {@code (end - start) + 1} characters in the set array. + * @throws IllegalArgumentException if {@code count} < 0 or the provided chars array is empty. * @since 2.0 */ public static String random(int count, int start, int end, boolean letters, boolean numbers, @@ -230,12 +227,20 @@ public class RandomStringUtils { } else if (count < 0) { throw new IllegalArgumentException("Requested random string length " + count + " is less than 0."); } - if ((start == 0) && (end == 0)) { - end = 'z' + 1; - start = ' '; - if (!letters && !numbers) { - start = 0; - end = Integer.MAX_VALUE; + if (chars != null && chars.length == 0) { + throw new IllegalArgumentException("The chars array must not be empty"); + } + + if (start == 0 && end == 0) { + if (chars != null) { + end = chars.length; + } else { + if (!letters && !numbers) { + end = Integer.MAX_VALUE; + } else { + end = 'z' + 1; + start = ' '; + } } } @@ -249,10 +254,9 @@ public class RandomStringUtils { } else { ch = chars[random.nextInt(gap) + start]; } - if ((letters && Character.isLetter(ch)) - || (numbers && Character.isDigit(ch)) - || (!letters && !numbers)) - { + if (letters && Character.isLetter(ch) + || numbers && Character.isDigit(ch) + || !letters && !numbers) { if(ch >= 56320 && ch <= 57343) { if(count == 0) { count++; @@ -289,13 +293,14 @@ public class RandomStringUtils { * specified.</p> * * <p>Characters will be chosen from the set of characters - * specified.</p> + * specified by the string, must not be empty. + * If null, the set of all characters is used.</p> * * @param count the length of random string to create * @param chars the String containing the set of characters to use, - * may be null + * may be null, but must not be empty * @return the random string - * @throws IllegalArgumentException if <code>count</code> < 0. + * @throws IllegalArgumentException if {@code count} < 0 or the string is empty. */ public static String random(int count, String chars) { if (chars == null) { @@ -314,7 +319,7 @@ public class RandomStringUtils { * @param chars the character array containing the set of characters to use, * may be null * @return the random string - * @throws IllegalArgumentException if <code>count</code> < 0. + * @throws IllegalArgumentException if {@code count} < 0. */ public static String random(int count, char[] chars) { if (chars == null) { Modified: commons/proper/lang/branches/LANG_2_X/src/site/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/site/changes/changes.xml?rev=1348424&r1=1348423&r2=1348424&view=diff ============================================================================== --- commons/proper/lang/branches/LANG_2_X/src/site/changes/changes.xml (original) +++ commons/proper/lang/branches/LANG_2_X/src/site/changes/changes.xml Sat Jun 9 15:06:14 2012 @@ -21,6 +21,7 @@ </properties> <body> <release version="2.7" date="TBA" description="TBA (requires minimum of Java 1.3)"> + <action issue="LANG-805" type="fix">RandomStringUtils.random(count, 0, 0, false, false, universe, random) always throws java.lang.ArrayIndexOutOfBoundsException</action> <action issue="LANG-803" type="fix">LocaleUtils - DCL idiom is not thread-safe.</action> <action issue="LANG-677" type="fix">DateUtils isSameLocalTime() compares the hour using 12hour Calendar.HOUR instead of 24hour Calendar.HOUR_OF_DAY</action> </release> Modified: commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/RandomStringUtilsTest.java URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/RandomStringUtilsTest.java?rev=1348424&r1=1348423&r2=1348424&view=diff ============================================================================== --- commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/RandomStringUtilsTest.java (original) +++ commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/RandomStringUtilsTest.java Sat Jun 9 15:06:14 2012 @@ -20,13 +20,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.Random; - /** * Unit tests {@link org.apache.commons.lang.RandomStringUtils}. * - * @author <a href="mailto:ste...@caswell.name">Steven Caswell</a> - * @author <a href="mailto:rides...@users.sourceforge.net">Ringo De Smet</a> - * @author Phil Steitz * @version $Id$ */ public class RandomStringUtilsTest extends junit.framework.TestCase { @@ -127,9 +123,15 @@ public class RandomStringUtilsTest exten r1 = RandomStringUtils.random(0); assertEquals("random(0).equals(\"\")", "", r1); + } + public void testLANG805() { + long seed = System.currentTimeMillis(); + assertEquals("aaa", RandomStringUtils.random(3,0,0,false,false,new char[]{'a'},new Random(seed))); } + public void testExceptions() { + final char[] DUMMY = new char[]{'a'}; // valid char array try { RandomStringUtils.random(-1); fail(); @@ -139,7 +141,11 @@ public class RandomStringUtilsTest exten fail(); } catch (IllegalArgumentException ex) {} try { - RandomStringUtils.random(-1, new char[0]); + RandomStringUtils.random(-1, DUMMY); + fail(); + } catch (IllegalArgumentException ex) {} + try { + RandomStringUtils.random(1, new char[0]); // must not provide empty array => IAE fail(); } catch (IllegalArgumentException ex) {} try { @@ -147,15 +153,19 @@ public class RandomStringUtilsTest exten fail(); } catch (IllegalArgumentException ex) {} try { + RandomStringUtils.random(-1, (String)null); + fail(); + } catch (IllegalArgumentException ex) {} + try { RandomStringUtils.random(-1, 'a', 'z', false, false); fail(); } catch (IllegalArgumentException ex) {} try { - RandomStringUtils.random(-1, 'a', 'z', false, false, new char[0]); + RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY); fail(); } catch (IllegalArgumentException ex) {} try { - RandomStringUtils.random(-1, 'a', 'z', false, false, new char[0], new Random()); + RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY, new Random()); fail(); } catch (IllegalArgumentException ex) {} } @@ -290,8 +300,8 @@ public class RandomStringUtilsTest exten double sumSq = 0.0d; double dev = 0.0d; for (int i = 0; i < observed.length; i++) { - dev = (double) (observed[i] - expected[i]); - sumSq += dev * dev / (double) expected[i]; + dev = observed[i] - expected[i]; + sumSq += dev * dev / expected[i]; } return sumSq; } @@ -315,8 +325,8 @@ public class RandomStringUtilsTest exten for (int i=0; i < orig.length() && i < copy.length(); i++) { char o = orig.charAt(i); char c = copy.charAt(i); - assertEquals("differs at " + i + "(" + Integer.toHexString((new Character(o)).hashCode()) + "," + - Integer.toHexString((new Character(c)).hashCode()) + ")", o, c); + assertEquals("differs at " + i + "(" + Integer.toHexString(new Character(o).hashCode()) + "," + + Integer.toHexString(new Character(c).hashCode()) + ")", o, c); } // compare length also assertEquals(orig.length(), copy.length());