Skip to content

Commit

Permalink
Merge f12360a into 1850b03
Browse files Browse the repository at this point in the history
  • Loading branch information
bianzheng123 committed May 28, 2020
2 parents 1850b03 + f12360a commit 1092163
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 39 deletions.
46 changes: 29 additions & 17 deletions src/main/java/com/github/javafaker/Number.java
Expand Up @@ -13,28 +13,34 @@ protected Number(Faker faker) {
* Returns a random number from 0-9 (both inclusive)
*/
public int randomDigit() {
return decimalBetween(0,10).intValue();
return decimalBetween(0, 10).intValue();
}

/**
* Returns a random number from 1-9 (both inclusive)
*/
public int randomDigitNotZero() {
return decimalBetween(1,10).intValue();
return decimalBetween(1, 10).intValue();
}

/**
* @see Number#numberBetween(long, long)
* @see Number#numberBetween(long, long)
*/
public int numberBetween(int min, int max) {
if (min == max) return min;

int value = decimalBetween(min,max).setScale(0, BigDecimal.ROUND_HALF_DOWN).intValue();
if (min > max) {
int tmp = max;
max = min;
min = tmp;
}

int value = decimalBetween(min, max).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
return value == max ? value - 1 : value;
}

/**
* Return a number between <em>min</em> and <em>max</em>. If
* Return a number between <em>min</em> and <em>max</em>. If
* min == max, then min is returned. So numberBetween(2,2) will yield 2 even though
* it doesn't make sense.
*
Expand All @@ -44,10 +50,16 @@ public int numberBetween(int min, int max) {
public long numberBetween(long min, long max) {
if (min == max) return min;

long value = decimalBetween(min, max).setScale(0, BigDecimal.ROUND_HALF_DOWN).longValue();
if (min > max) {
long tmp = max;
max = min;
min = tmp;
}

long value = decimalBetween(min, max).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
return value == max ? value - 1 : value;
}

/**
* @param numberOfDigits the number of digits the generated value should have
* @param strict whether or not the generated value should have exactly <code>numberOfDigits</code>
Expand All @@ -66,13 +78,14 @@ public long randomNumber(int numberOfDigits, boolean strict) {
* Returns a random number
*/
public long randomNumber() {
int numberOfDigits = decimalBetween(1,10).intValue();
int numberOfDigits = decimalBetween(1, 10).intValue();
return randomNumber(numberOfDigits, false);
}

public double randomDouble(int maxNumberOfDecimals, int min, int max) {
return randomDouble(maxNumberOfDecimals,(long) min, (long) max);
return randomDouble(maxNumberOfDecimals, (long) min, (long) max);
}

/**
* Returns a random double
*
Expand All @@ -81,7 +94,7 @@ public double randomDouble(int maxNumberOfDecimals, int min, int max) {
* @param max maximum value
*/
public double randomDouble(int maxNumberOfDecimals, long min, long max) {
return decimalBetween(min,max)
return decimalBetween(min, max)
.setScale(maxNumberOfDecimals, BigDecimal.ROUND_HALF_DOWN)
.doubleValue();
}
Expand All @@ -99,14 +112,13 @@ private BigDecimal decimalBetween(long min, long max) {
final long trueMax = Math.max(min, max);

final double range = (double) trueMax - (double) trueMin;

final double chunkCount = Math.sqrt(Math.abs(range));
final double chunkSize = chunkCount;
final long randomChunk = faker.random().nextLong((long) chunkCount);

final double chunkStart = trueMin + randomChunk * chunkSize;
final double adj = chunkSize * faker.random().nextDouble();
return new BigDecimal(chunkStart + adj);
final double chunkCount = Math.sqrt(Math.abs(range));
final long decimalOfChunkCount = (long) Math.ceil(chunkCount);
final long randomChunk = faker.random().nextLong(decimalOfChunkCount);
final double chunkStart = trueMin + randomChunk * chunkCount;
final double adj = chunkCount * faker.random().nextDouble();
return chunkStart + adj >= trueMax ? new BigDecimal(trueMax - 1) : new BigDecimal(chunkStart + adj);
}

public String digits(int count) {
Expand Down
12 changes: 11 additions & 1 deletion src/test/java/com/github/javafaker/DateAndTimeTest.java
Expand Up @@ -11,7 +11,7 @@
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.*;

/**
* @author pmiklos
Expand Down Expand Up @@ -115,4 +115,14 @@ public void testBirthdayWithAges() {
}
}

@Test
public void testBetweenThenLargerThanNow(){
try{
Date now = new Date();
Date then = new Date(now.getTime() + 1000);
Date date =faker.date().between(then,now);
fail("Should be exception");}catch (IllegalArgumentException e){
assertEquals("Invalid date range, the upper bound date is before the lower bound.", e.getMessage());
}
}
}
75 changes: 54 additions & 21 deletions src/test/java/com/github/javafaker/NumberTest.java
Expand Up @@ -5,6 +5,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -27,7 +28,7 @@ public class NumberTest extends AbstractFakerTest {
private static final int RANDOMIZATION_QUALITY_RANGE_START = RANDOMIZATION_QUALITY_RANGE_STEP;
public static final int RANDOMIZATION_TESTS_MAX_NUMBERS_TO_GET = 1000;

final double individualRunGtPercentUnique= 0.8;
final double individualRunGtPercentUnique = 0.8;
final double percentRunsGtUniquePercentage = 0.90;

@Test
Expand Down Expand Up @@ -185,18 +186,18 @@ public void numberBetweenLongLongZeroMinMax() {
assertThat("Calling numberBetween with min==max yields min, with 0",
faker.number().numberBetween(0L, 0L),
is(0L));
assertThat("Calling numberBetween with min==max yields min",
assertThat("Calling numberBetween with min==max yields min",
faker.number().numberBetween(2L, 2L),
is(2L));
}

/**
* Given a number of min/max ranges
* for each min/max range, call {@link Number#randomDouble(int, int, int)} with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* for each min/max range, call {@link Number#randomDouble(int, int, int)} with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* For all 'uniqueness' values
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
*
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
* <p>
* This isn't perfect but it ensures a pretty good degree of uniqueness in the random number generation.
*/
@Test
Expand Down Expand Up @@ -229,11 +230,11 @@ public Double call() throws Exception {

/**
* Given a number of min/max ranges
* for each min/max range, call numberBetween with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* for each min/max range, call numberBetween with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* For all 'uniqueness' values
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
*
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
* <p>
* This isn't perfect but it ensures a pretty good degree of uniqueness in the random number generation.
*/
@Test
Expand Down Expand Up @@ -267,11 +268,11 @@ public Integer call() throws Exception {

/**
* Given a number of min/max ranges
* for each min/max range, call {@link Number#numberBetween(long, long)} with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* for each min/max range, call {@link Number#numberBetween(long, long)} with min/max 'n' times
* calculate the uniqueness for that given min/max range.
* For all 'uniqueness' values
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
*
* verify the percentage of 'uniqueness' ratios over 80% is 90%.
* <p>
* This isn't perfect but it ensures a pretty good degree of uniqueness in the random number generation.
*/
@Test
Expand All @@ -290,7 +291,7 @@ public Long call() throws Exception {
});
}
};

final double percentGreaterThan80Percent = randomizationQualityTest(individualRunGtPercentUnique, minMaxRangeToUniquePercentageFunction);
assertThat("Percentage of runs > 80% unique is gte 90%",
percentGreaterThan80Percent, greaterThanOrEqualTo(percentRunsGtUniquePercentage));
Expand Down Expand Up @@ -325,19 +326,51 @@ public void testDigits() {
assertThat(digits, matchesRegularExpression("[0-9]{5}"));
}

@Test
public void testGenerateMax_1Int() {
boolean hasMax_1 = true;
outer:
for (int i = 1; i <= 1000; i++) {
for (int j = 0; j < 100000; j++) {
int r = faker.number().numberBetween(0, i);
if (r == i - 1) {
continue outer;
}
}
hasMax_1 = false;
}
Assert.assertTrue(hasMax_1);
}

@Test
public void testGenerateMax_1Long() {
boolean hasMax_1 = true;
outer:
for (long i = 1; i <= 1000; i++) {
for (long j = 0; j < 100000; j++) {
long r = faker.number().numberBetween(0, i);
if (r == i - 1) {
continue outer;
}
}
hasMax_1 = false;
}
Assert.assertTrue(hasMax_1);
}

/**
* Over the series of numbers identified from RANDOMIZATION_QUALITY_RANGE_START to
* RANDOMIZATION_QUALITY_RANGE_END, create a min/max range of -value/value and
* with of those min/max values, call <em>percentUniqueRunner</em>.
*
* <p>
* Collect the number of calls to <em>percentUniqueRunner</em> that were
* above the threshold and finally return that number divided by the total number of calls to
* <em>percentUniqueRunner</em>.
*
*
* @return percent of percentUniqueRunner's results greater than the threshold
*/
private double randomizationQualityTest(final double threshold,
final Function<Pair<Long,Long>,Double> percentUniqueRunner) {
private double randomizationQualityTest(final double threshold,
final Function<Pair<Long, Long>, Double> percentUniqueRunner) {
final int rangeEnd = RANDOMIZATION_QUALITY_RANGE_END;
final int rangeStep = RANDOMIZATION_QUALITY_RANGE_STEP;
final int rangeStart = RANDOMIZATION_QUALITY_RANGE_START;
Expand All @@ -346,7 +379,7 @@ private double randomizationQualityTest(final double threshold,
final AtomicLong total = new AtomicLong();

for (long l = rangeStart; l < rangeEnd; l += rangeStep) {
final double percentUnique = percentUniqueRunner.apply(Pair.of(-l,l));
final double percentUnique = percentUniqueRunner.apply(Pair.of(-l, l));
logger.info("Range {} to {} is {} percent unique.", -l, l, percentUnique);
if (percentUnique > threshold) {
greaterThanThreshold.incrementAndGet();
Expand All @@ -357,7 +390,7 @@ private double randomizationQualityTest(final double threshold,
return (double) greaterThanThreshold.get() / (double) total.get();
}


/**
* Given a number of iterations, calls <em>callable</em> 'iterations' times and collects the results,
* then calculates the number of results that were unique and returns the percentage that where unique.
Expand Down

0 comments on commit 1092163

Please sign in to comment.