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