• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.lang3;
18 
19 import static org.hamcrest.MatcherAssert.assertThat;
20 import static org.hamcrest.Matchers.allOf;
21 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
22 import static org.hamcrest.Matchers.is;
23 import static org.hamcrest.Matchers.lessThanOrEqualTo;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertThrows;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29 import static org.junit.jupiter.api.Assertions.fail;
30 
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.Modifier;
33 import java.nio.charset.Charset;
34 import java.nio.charset.StandardCharsets;
35 import java.util.Random;
36 
37 import org.junit.jupiter.api.Test;
38 
39 /**
40  * Unit tests {@link org.apache.commons.lang3.RandomStringUtils}.
41  */
42 public class RandomStringUtilsTest extends AbstractLangTest {
43 
44     @Test
testConstructor()45     public void testConstructor() {
46         assertNotNull(new RandomStringUtils());
47         final Constructor<?>[] cons = RandomStringUtils.class.getDeclaredConstructors();
48         assertEquals(1, cons.length);
49         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
50         assertTrue(Modifier.isPublic(RandomStringUtils.class.getModifiers()));
51         assertFalse(Modifier.isFinal(RandomStringUtils.class.getModifiers()));
52     }
53 
54     /**
55      * Test the implementation
56      */
57     @Test
testRandomStringUtils()58     public void testRandomStringUtils() {
59         String r1 = RandomStringUtils.random(50);
60         assertEquals(50, r1.length(), "random(50) length");
61         String r2 = RandomStringUtils.random(50);
62         assertEquals(50, r2.length(), "random(50) length");
63         assertFalse(r1.equals(r2), "!r1.equals(r2)");
64 
65         r1 = RandomStringUtils.randomAscii(50);
66         assertEquals(50, r1.length(), "randomAscii(50) length");
67         for (int i = 0; i < r1.length(); i++) {
68             assertTrue(r1.charAt(i) >= 32 && r1.charAt(i) <= 127, "char between 32 and 127");
69         }
70         r2 = RandomStringUtils.randomAscii(50);
71         assertFalse(r1.equals(r2), "!r1.equals(r2)");
72 
73         r1 = RandomStringUtils.randomAlphabetic(50);
74         assertEquals(50, r1.length(), "randomAlphabetic(50)");
75         for (int i = 0; i < r1.length(); i++) {
76             assertTrue(Character.isLetter(r1.charAt(i)) && !Character.isDigit(r1.charAt(i)), "r1 contains alphabetic");
77         }
78         r2 = RandomStringUtils.randomAlphabetic(50);
79         assertFalse(r1.equals(r2), "!r1.equals(r2)");
80 
81         r1 = RandomStringUtils.randomAlphanumeric(50);
82         assertEquals(50, r1.length(), "randomAlphanumeric(50)");
83         for (int i = 0; i < r1.length(); i++) {
84             assertTrue(Character.isLetterOrDigit(r1.charAt(i)), "r1 contains alphanumeric");
85         }
86         r2 = RandomStringUtils.randomAlphabetic(50);
87         assertFalse(r1.equals(r2), "!r1.equals(r2)");
88 
89         r1 = RandomStringUtils.randomGraph(50);
90         assertEquals(50, r1.length(), "randomGraph(50) length");
91         for (int i = 0; i < r1.length(); i++) {
92             assertTrue(r1.charAt(i) >= 33 && r1.charAt(i) <= 126, "char between 33 and 126");
93         }
94         r2 = RandomStringUtils.randomGraph(50);
95         assertFalse(r1.equals(r2), "!r1.equals(r2)");
96 
97         r1 = RandomStringUtils.randomNumeric(50);
98         assertEquals(50, r1.length(), "randomNumeric(50)");
99         for (int i = 0; i < r1.length(); i++) {
100             assertTrue(Character.isDigit(r1.charAt(i)) && !Character.isLetter(r1.charAt(i)), "r1 contains numeric");
101         }
102         r2 = RandomStringUtils.randomNumeric(50);
103         assertFalse(r1.equals(r2), "!r1.equals(r2)");
104 
105         r1 = RandomStringUtils.randomPrint(50);
106         assertEquals(50, r1.length(), "randomPrint(50) length");
107         for (int i = 0; i < r1.length(); i++) {
108             assertTrue(r1.charAt(i) >= 32 && r1.charAt(i) <= 126, "char between 32 and 126");
109         }
110         r2 = RandomStringUtils.randomPrint(50);
111         assertFalse(r1.equals(r2), "!r1.equals(r2)");
112 
113         String set = "abcdefg";
114         r1 = RandomStringUtils.random(50, set);
115         assertEquals(50, r1.length(), "random(50, \"abcdefg\")");
116         for (int i = 0; i < r1.length(); i++) {
117             assertTrue(set.indexOf(r1.charAt(i)) > -1, "random char in set");
118         }
119         r2 = RandomStringUtils.random(50, set);
120         assertFalse(r1.equals(r2), "!r1.equals(r2)");
121 
122         r1 = RandomStringUtils.random(50, (String) null);
123         assertEquals(50, r1.length(), "random(50) length");
124         r2 = RandomStringUtils.random(50, (String) null);
125         assertEquals(50, r2.length(), "random(50) length");
126         assertFalse(r1.equals(r2), "!r1.equals(r2)");
127 
128         set = "stuvwxyz";
129         r1 = RandomStringUtils.random(50, set.toCharArray());
130         assertEquals(50, r1.length(), "random(50, \"stuvwxyz\")");
131         for (int i = 0; i < r1.length(); i++) {
132             assertTrue(set.indexOf(r1.charAt(i)) > -1, "random char in set");
133         }
134         r2 = RandomStringUtils.random(50, set);
135         assertFalse(r1.equals(r2), "!r1.equals(r2)");
136 
137         r1 = RandomStringUtils.random(50, (char[]) null);
138         assertEquals(50, r1.length(), "random(50) length");
139         r2 = RandomStringUtils.random(50, (char[]) null);
140         assertEquals(50, r2.length(), "random(50) length");
141         assertFalse(r1.equals(r2), "!r1.equals(r2)");
142 
143         final long seedMillis = System.currentTimeMillis();
144         r1 = RandomStringUtils.random(50, 0, 0, true, true, null, new Random(seedMillis));
145         r2 = RandomStringUtils.random(50, 0, 0, true, true, null, new Random(seedMillis));
146         assertEquals(r1, r2, "r1.equals(r2)");
147 
148         r1 = RandomStringUtils.random(0);
149         assertEquals("", r1, "random(0).equals(\"\")");
150     }
151 
152     @Test
testLANG805()153     public void testLANG805() {
154         final long seedMillis = System.currentTimeMillis();
155         assertEquals("aaa", RandomStringUtils.random(3, 0, 0, false, false, new char[]{'a'}, new Random(seedMillis)));
156     }
157 
158     @Test
testLANG807()159     public void testLANG807() {
160         final IllegalArgumentException ex =
161                 assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(3, 5, 5, false, false));
162         final String msg = ex.getMessage();
163         assertTrue(msg.contains("start"), "Message (" + msg + ") must contain 'start'");
164         assertTrue(msg.contains("end"), "Message (" + msg + ") must contain 'end'");
165     }
166 
167     @Test
testExceptions()168     public void testExceptions() {
169         final char[] DUMMY = {'a'}; // valid char array
170         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1));
171         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, true, true));
172         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, DUMMY));
173         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(1, new char[0]));
174         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, ""));
175         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, (String) null));
176         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false));
177         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY));
178         assertThrows(
179                 IllegalArgumentException.class,
180                 () -> RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY, new Random()));
181         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(8, 32, 48, false, true));
182         assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(8, 32, 65, true, false));
183     }
184 
185     /**
186      * Make sure boundary alphanumeric characters are generated by randomAlphaNumeric
187      * This test will fail randomly with probability = 6 * (61/62)**1000 ~ 5.2E-7
188      */
189     @Test
testRandomAlphaNumeric()190     public void testRandomAlphaNumeric() {
191         final char[] testChars = {'a', 'z', 'A', 'Z', '0', '9'};
192         final boolean[] found = {false, false, false, false, false, false};
193         for (int i = 0; i < 100; i++) {
194             final String randString = RandomStringUtils.randomAlphanumeric(10);
195             for (int j = 0; j < testChars.length; j++) {
196                 if (randString.indexOf(testChars[j]) > 0) {
197                     found[j] = true;
198                 }
199             }
200         }
201         for (int i = 0; i < testChars.length; i++) {
202             assertTrue(found[i],
203                     "alphanumeric character not generated in 1000 attempts: " +
204                             testChars[i] + " -- repeated failures indicate a problem ");
205         }
206     }
207 
208     /**
209      * Make sure '0' and '9' are generated by randomNumeric
210      * This test will fail randomly with probability = 2 * (9/10)**1000 ~ 3.5E-46
211      */
212     @Test
testRandomNumeric()213     public void testRandomNumeric() {
214         final char[] testChars = {'0', '9'};
215         final boolean[] found = {false, false};
216         for (int i = 0; i < 100; i++) {
217             final String randString = RandomStringUtils.randomNumeric(10);
218             for (int j = 0; j < testChars.length; j++) {
219                 if (randString.indexOf(testChars[j]) > 0) {
220                     found[j] = true;
221                 }
222             }
223         }
224         for (int i = 0; i < testChars.length; i++) {
225             assertTrue(found[i],
226                     "digit not generated in 1000 attempts: " + testChars[i] +
227                             " -- repeated failures indicate a problem ");
228         }
229     }
230 
231     /**
232      * Make sure boundary alpha characters are generated by randomAlphabetic
233      * This test will fail randomly with probability = 4 * (51/52)**1000 ~ 1.58E-8
234      */
235     @Test
testRandomAlphabetic()236     public void testRandomAlphabetic() {
237         final char[] testChars = {'a', 'z', 'A', 'Z'};
238         final boolean[] found = {false, false, false, false};
239         for (int i = 0; i < 100; i++) {
240             final String randString = RandomStringUtils.randomAlphabetic(10);
241             for (int j = 0; j < testChars.length; j++) {
242                 if (randString.indexOf(testChars[j]) > 0) {
243                     found[j] = true;
244                 }
245             }
246         }
247         for (int i = 0; i < testChars.length; i++) {
248             assertTrue(found[i],
249                     "alphanumeric character not generated in 1000 attempts: " + testChars[i] +
250                             " -- repeated failures indicate a problem ");
251         }
252     }
253 
254     /**
255      * Make sure 32 and 127 are generated by randomNumeric
256      * This test will fail randomly with probability = 2*(95/96)**1000 ~ 5.7E-5
257      */
258     @Test
testRandomAscii()259     public void testRandomAscii() {
260         final char[] testChars = {(char) 32, (char) 126};
261         final boolean[] found = {false, false};
262         for (int i = 0; i < 100; i++) {
263             final String randString = RandomStringUtils.randomAscii(10);
264             for (int j = 0; j < testChars.length; j++) {
265                 if (randString.indexOf(testChars[j]) > 0) {
266                     found[j] = true;
267                 }
268             }
269         }
270         for (int i = 0; i < testChars.length; i++) {
271             assertTrue(found[i],
272                     "ascii character not generated in 1000 attempts: " + (int) testChars[i] +
273                             " -- repeated failures indicate a problem");
274         }
275     }
276 
277     @Test
testRandomAsciiRange()278     public void testRandomAsciiRange() {
279         final int expectedMinLengthInclusive = 1;
280         final int expectedMaxLengthExclusive = 11;
281         final String pattern = "^\\p{ASCII}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
282 
283         int maxCreatedLength = expectedMinLengthInclusive;
284         int minCreatedLength = expectedMaxLengthExclusive - 1;
285         for (int i = 0; i < 1000; i++) {
286             final String s = RandomStringUtils.randomAscii(expectedMinLengthInclusive, expectedMaxLengthExclusive);
287             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
288             assertTrue(s.matches(pattern), s);
289 
290             if (s.length() < minCreatedLength) {
291                 minCreatedLength = s.length();
292             }
293 
294             if (s.length() > maxCreatedLength) {
295                 maxCreatedLength = s.length();
296             }
297         }
298         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
299         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
300     }
301 
302     @Test
testRandomAlphabeticRange()303     public void testRandomAlphabeticRange() {
304         final int expectedMinLengthInclusive = 1;
305         final int expectedMaxLengthExclusive = 11;
306         final String pattern = "^\\p{Alpha}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
307 
308         int maxCreatedLength = expectedMinLengthInclusive;
309         int minCreatedLength = expectedMaxLengthExclusive - 1;
310         for (int i = 0; i < 1000; i++) {
311             final String s = RandomStringUtils.randomAlphabetic(expectedMinLengthInclusive, expectedMaxLengthExclusive);
312             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
313             assertTrue(s.matches(pattern), s);
314 
315             if (s.length() < minCreatedLength) {
316                 minCreatedLength = s.length();
317             }
318 
319             if (s.length() > maxCreatedLength) {
320                 maxCreatedLength = s.length();
321             }
322         }
323         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
324         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
325     }
326 
327     @Test
testRandomAlphanumericRange()328     public void testRandomAlphanumericRange() {
329         final int expectedMinLengthInclusive = 1;
330         final int expectedMaxLengthExclusive = 11;
331         final String pattern = "^\\p{Alnum}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
332 
333         int maxCreatedLength = expectedMinLengthInclusive;
334         int minCreatedLength = expectedMaxLengthExclusive - 1;
335         for (int i = 0; i < 1000; i++) {
336             final String s = RandomStringUtils.randomAlphanumeric(expectedMinLengthInclusive, expectedMaxLengthExclusive);
337             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
338             assertTrue(s.matches(pattern), s);
339 
340             if (s.length() < minCreatedLength) {
341                 minCreatedLength = s.length();
342             }
343 
344             if (s.length() > maxCreatedLength) {
345                 maxCreatedLength = s.length();
346             }
347         }
348         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
349         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
350     }
351 
352     @Test
testRandomGraphRange()353     public void testRandomGraphRange() {
354         final int expectedMinLengthInclusive = 1;
355         final int expectedMaxLengthExclusive = 11;
356         final String pattern = "^\\p{Graph}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
357 
358         int maxCreatedLength = expectedMinLengthInclusive;
359         int minCreatedLength = expectedMaxLengthExclusive - 1;
360         for (int i = 0; i < 1000; i++) {
361             final String s = RandomStringUtils.randomGraph(expectedMinLengthInclusive, expectedMaxLengthExclusive);
362             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
363             assertTrue(s.matches(pattern), s);
364 
365             if (s.length() < minCreatedLength) {
366                 minCreatedLength = s.length();
367             }
368 
369             if (s.length() > maxCreatedLength) {
370                 maxCreatedLength = s.length();
371             }
372         }
373         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
374         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
375     }
376 
377     @Test
testRandomNumericRange()378     public void testRandomNumericRange() {
379         final int expectedMinLengthInclusive = 1;
380         final int expectedMaxLengthExclusive = 11;
381         final String pattern = "^\\p{Digit}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
382 
383         int maxCreatedLength = expectedMinLengthInclusive;
384         int minCreatedLength = expectedMaxLengthExclusive - 1;
385         for (int i = 0; i < 1000; i++) {
386             final String s = RandomStringUtils.randomNumeric(expectedMinLengthInclusive, expectedMaxLengthExclusive);
387             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
388             assertTrue(s.matches(pattern), s);
389 
390             if (s.length() < minCreatedLength) {
391                 minCreatedLength = s.length();
392             }
393 
394             if (s.length() > maxCreatedLength) {
395                 maxCreatedLength = s.length();
396             }
397         }
398         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
399         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
400     }
401 
402     @Test
testRandomPrintRange()403     public void testRandomPrintRange() {
404         final int expectedMinLengthInclusive = 1;
405         final int expectedMaxLengthExclusive = 11;
406         final String pattern = "^\\p{Print}{" + expectedMinLengthInclusive + ',' + expectedMaxLengthExclusive + "}$";
407 
408         int maxCreatedLength = expectedMinLengthInclusive;
409         int minCreatedLength = expectedMaxLengthExclusive - 1;
410         for (int i = 0; i < 1000; i++) {
411             final String s = RandomStringUtils.randomPrint(expectedMinLengthInclusive, expectedMaxLengthExclusive);
412             assertThat("within range", s.length(), allOf(greaterThanOrEqualTo(expectedMinLengthInclusive), lessThanOrEqualTo(expectedMaxLengthExclusive - 1)));
413             assertTrue(s.matches(pattern), s);
414 
415             if (s.length() < minCreatedLength) {
416                 minCreatedLength = s.length();
417             }
418 
419             if (s.length() > maxCreatedLength) {
420                 maxCreatedLength = s.length();
421             }
422         }
423         assertThat("min generated, may fail randomly rarely", minCreatedLength, is(expectedMinLengthInclusive));
424         assertThat("max generated, may fail randomly rarely", maxCreatedLength, is(expectedMaxLengthExclusive - 1));
425     }
426 
427     /**
428      * Test homogeneity of random strings generated --
429      * i.e., test that characters show up with expected frequencies
430      * in generated strings.  Will fail randomly about 1 in 1000 times.
431      * Repeated failures indicate a problem.
432      */
433     @Test
testRandomStringUtilsHomog()434     public void testRandomStringUtilsHomog() {
435         final String set = "abc";
436         final char[] chars = set.toCharArray();
437         String gen = "";
438         final int[] counts = {0, 0, 0};
439         final int[] expected = {200, 200, 200};
440         for (int i = 0; i< 100; i++) {
441             gen = RandomStringUtils.random(6, chars);
442             for (int j = 0; j < 6; j++) {
443                 switch (gen.charAt(j)) {
444                     case 'a': {
445                         counts[0]++;
446                         break;
447                     }
448                     case 'b': {
449                         counts[1]++;
450                         break;
451                     }
452                     case 'c': {
453                         counts[2]++;
454                         break;
455                     }
456                     default: {
457                         fail("generated character not in set");
458                     }
459                 }
460             }
461         }
462         // Perform chi-square test with df = 3-1 = 2, testing at .001 level
463         assertTrue(chiSquare(expected, counts) < 13.82, "test homogeneity -- will fail about 1 in 1000 times");
464     }
465 
466     /**
467      * Computes Chi-Square statistic given observed and expected counts
468      * @param observed array of observed frequency counts
469      * @param expected array of expected frequency counts
470      */
471     private double chiSquare(final int[] expected, final int[] observed) {
472         double sumSq = 0.0d;
473         double dev = 0.0d;
474         for (int i = 0; i < observed.length; i++) {
475             dev = observed[i] - expected[i];
476             sumSq += dev * dev / expected[i];
477         }
478         return sumSq;
479     }
480 
481     /**
482      * Checks if the string got by {@link RandomStringUtils#random(int)}
483      * can be converted to UTF-8 and back without loss.
484      *
485      * @see <a href="https://issues.apache.org/jira/browse/LANG-100">LANG-100</a>
486      */
487     @Test
488     public void testLang100() {
489         final int size = 5000;
490         final Charset charset = StandardCharsets.UTF_8;
491         final String orig = RandomStringUtils.random(size);
492         final byte[] bytes = orig.getBytes(charset);
493         final String copy = new String(bytes, charset);
494 
495         // for a verbose compare:
496         for (int i=0; i < orig.length() && i < copy.length(); i++) {
497             final char o = orig.charAt(i);
498             final char c = copy.charAt(i);
499             assertEquals(o, c,
500                     "differs at " + i + "(" + Integer.toHexString(Character.valueOf(o).hashCode()) + "," +
501                             Integer.toHexString(Character.valueOf(c).hashCode()) + ")");
502         }
503         // compare length also
504         assertEquals(orig.length(), copy.length());
505         // just to be complete
506         assertEquals(orig, copy);
507     }
508 
509 
510     /**
511      * Test for LANG-1286. Creates situation where old code would
512      * overflow a char and result in a code point outside the specified
513      * range.
514      */
515     @Test
516     public void testCharOverflow() {
517         final int start = Character.MAX_VALUE;
518         final int end = Integer.MAX_VALUE;
519 
520         @SuppressWarnings("serial")
521         final
522         Random fixedRandom = new Random() {
523             @Override
524             public int nextInt(final int n) {
525                 // Prevents selection of 'start' as the character
526                 return super.nextInt(n - 1) + 1;
527             }
528         };
529 
530         final String result = RandomStringUtils.random(2, start, end, false, false, null, fixedRandom);
531         final int c = result.codePointAt(0);
532         assertTrue(c >= start && c < end, String.format("Character '%d' not in range [%d,%d).", c, start, end));
533     }
534 }
535 
536