-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test-utils: RandomUtils is deprecated, TRandom class introduced
Signed-off-by: Ketoth Xupack <ketoth.xupack@gmail.com>
- Loading branch information
1 parent
585a6eb
commit 8766443
Showing
3 changed files
with
289 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
181 changes: 181 additions & 0 deletions
181
projects/test-utils/src/main/java/org/nohope/test/TRandom.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
package org.nohope.test; | ||
|
||
import org.joda.time.DateTime; | ||
import org.joda.time.chrono.ISOChronology; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.util.Random; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.ThreadLocalRandom; | ||
|
||
/** | ||
* @author <a href="mailto:ketoth.xupack@gmail.com">ketoth xupack</a> | ||
* @since 9/21/12 6:55 PM | ||
*/ | ||
public final class TRandom { | ||
public static final String LOWER = "abcdefghijklmnopqrstuvwxyz"; | ||
public static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
public static final String DIGIT = "0123456789"; | ||
public static final String SPECIAL = "~`!@#$%^&*()_+-={}[]:\";'<>?,./|\\"; | ||
|
||
private final Callable<Random> randomGetter; | ||
|
||
private TRandom(final Callable<Random> randomGetter) { | ||
this.randomGetter = randomGetter; | ||
} | ||
|
||
/** @return TRandom instance based on {@link ThreadLocalRandom} class */ | ||
public static TRandom threadLocal() { | ||
return new TRandom(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
return ThreadLocalRandom.current(); | ||
} | ||
}); | ||
} | ||
|
||
/** @return TRandom instance based on {@link Random} class */ | ||
public static TRandom standard() { | ||
return new TRandom(new Callable<Random>() { | ||
private final Random rnd = new Random(); | ||
|
||
@Override | ||
public Random call() throws Exception { | ||
return rnd; | ||
} | ||
}); | ||
} | ||
|
||
/** @return TRandom instance based on single random instance */ | ||
public static TRandom singleton(@Nonnull final Random rnd) { | ||
return new TRandom(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
return rnd; | ||
} | ||
}); | ||
} | ||
|
||
/** @return TRandom instance based on thread-local random instance */ | ||
public static TRandom threadLocal(@Nonnull final Callable<Random> rnd) { | ||
final ThreadLocal<Random> local = new ThreadLocal<Random>() { | ||
@Override | ||
protected Random initialValue() { | ||
try { | ||
return rnd.call(); | ||
} catch (final Exception e) { | ||
throw new IllegalStateException(e); | ||
} | ||
} | ||
}; | ||
|
||
return new TRandom(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
return local.get(); | ||
} | ||
}); | ||
} | ||
|
||
private Random get() { | ||
try { | ||
final Random rnd = randomGetter.call(); | ||
if (rnd != null) { | ||
return rnd; | ||
} | ||
} catch (final Exception e) { | ||
throw new IllegalStateException(e); | ||
} | ||
|
||
throw new IllegalStateException("random instance is null"); | ||
} | ||
|
||
/** | ||
* Generates random string with given length and mask. | ||
* <p /> | ||
* Mask is a string which may contain next chars: | ||
* <ul> | ||
* <li>{@code A} for {@link TRandom#UPPER upper case} letter</li> | ||
* <li>{@code a} for {@link TRandom#LOWER lower case} letter</li> | ||
* <li>{@code #} for {@link TRandom#DIGIT digit}</li> | ||
* <li>{@code !} for {@link TRandom#SPECIAL special character}</li> | ||
* </ul> | ||
* | ||
* Example: | ||
* <pre> | ||
* RandomUtils.nextString(10, "#A!"); // `XH(^=>70; | ||
* </pre> | ||
* | ||
* @param length target string length | ||
* @param mask mask | ||
* @return randomly generated string | ||
*/ | ||
public String nextString(final int length, final String mask) { | ||
String resultMask = ""; | ||
if (mask.indexOf('a') > -1) { | ||
resultMask += LOWER; | ||
} | ||
if (mask.indexOf('A') > -1) { | ||
resultMask += UPPER; | ||
} | ||
if (mask.indexOf('#') > -1) { | ||
resultMask += DIGIT; | ||
} | ||
if (mask.indexOf('!') > -1) { | ||
resultMask += SPECIAL; | ||
} | ||
|
||
if ("".equals(mask)) { | ||
throw new IllegalArgumentException("Mask should contain at last one char from 'aA#!' sequence"); | ||
} | ||
|
||
final StringBuilder result = new StringBuilder(); | ||
for (int i = length; i > 0; --i) { | ||
result.append(resultMask.charAt(get().nextInt(resultMask.length()))); | ||
} | ||
return result.toString(); | ||
} | ||
|
||
/** | ||
* Generates random string with varying length from {@code 0} to given upper bound value exclusive. | ||
* <p /> | ||
* This version of string generator users {@code "aA#!"} mask. | ||
* | ||
* @param upperBound length | ||
* @return randomly generated string with varying length | ||
* @see TRandom#nextString(int, String) | ||
*/ | ||
public String nextString(final int upperBound) { | ||
return nextString(get().nextInt(upperBound), "aA#!"); | ||
} | ||
|
||
/** | ||
* Generates random string with varying length from {@code 0} to {@code 100} exclusive. | ||
* | ||
* @return randomly generated string with varying length | ||
* @see TRandom#nextString(int) | ||
*/ | ||
public String nextString() { | ||
return nextString(100); | ||
} | ||
|
||
public int nextInt() { | ||
return get().nextInt(); | ||
} | ||
|
||
public DateTime nextUtcDateTime() { | ||
return DateTime.now(ISOChronology.getInstanceUTC()); | ||
} | ||
|
||
public long nextLong() { | ||
return get().nextLong(); | ||
} | ||
|
||
public boolean nextBoolean() { | ||
return get().nextBoolean(); | ||
} | ||
|
||
public double nextDouble() { | ||
return get().nextDouble(); | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
projects/test-utils/src/test/java/org/nohope/test/TRandomTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package org.nohope.test; | ||
|
||
import org.junit.Test; | ||
|
||
import java.security.SecureRandom; | ||
import java.util.Random; | ||
import java.util.concurrent.Callable; | ||
import java.util.regex.Pattern; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
/** | ||
* @author <a href="mailto:ketoth.xupack@gmail.com">ketoth xupack</a> | ||
* @since 9/30/13 9:02 PM | ||
*/ | ||
public class TRandomTest { | ||
private static final Pattern ALL = Pattern.compile("."); | ||
|
||
private static final TRandom[] RNDS = { | ||
TRandom.standard(), | ||
TRandom.threadLocal(), | ||
TRandom.singleton(new SecureRandom()), | ||
TRandom.threadLocal(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
return new SecureRandom(); | ||
} | ||
}) | ||
}; | ||
|
||
@Test | ||
public void naive() { | ||
for (final TRandom rnd : RNDS) { | ||
rnd.nextInt(); | ||
rnd.nextLong(); | ||
rnd.nextDouble(); | ||
rnd.nextBoolean(); | ||
rnd.nextUtcDateTime(); | ||
} | ||
} | ||
|
||
@Test | ||
public void randomString() { | ||
for (final TRandom rnd : RNDS) { | ||
assertContainsAll(rnd.nextString(10, "a"), TRandom.LOWER, 10); | ||
assertContainsAll(rnd.nextString(10, "A"), TRandom.UPPER, 10); | ||
assertContainsAll(rnd.nextString(10, "#"), TRandom.DIGIT, 10); | ||
assertContainsAll(rnd.nextString(10, "!"), TRandom.SPECIAL, 10); | ||
|
||
assertTrue(rnd.nextString(10).length() <= 10); | ||
assertTrue(rnd.nextString().length() <= 100); | ||
|
||
try { | ||
RandomUtils.nextString(10, ""); | ||
fail(); | ||
} catch (final IllegalArgumentException ignored) { | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
public void failure() { | ||
final TRandom rnd = TRandom.threadLocal(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
return null; | ||
} | ||
}); | ||
|
||
try { | ||
rnd.nextInt(); | ||
fail(); | ||
} catch (final IllegalStateException e) { | ||
} | ||
|
||
final TRandom rnd2 = TRandom.threadLocal(new Callable<Random>() { | ||
@Override | ||
public Random call() throws Exception { | ||
throw new Exception("test"); | ||
} | ||
}); | ||
|
||
try { | ||
rnd2.nextInt(); | ||
fail(); | ||
} catch (final IllegalStateException e) { | ||
} | ||
} | ||
|
||
private static void assertContainsAll(final String target, final String source, final int length) { | ||
assertEquals(length, target.length()); | ||
for (final String s : ALL.split(source)) { | ||
if (!target.contains(s)) { | ||
fail(); | ||
} | ||
} | ||
} | ||
} |