Skip to content

Commit

Permalink
Randomize temporal units in DurationRandomizer
Browse files Browse the repository at this point in the history
This change makes DurationRandomizer generate random ChronoUnits instead of
using a fixed ChronoUnit.HOURS.
  • Loading branch information
lutovich committed Sep 26, 2019
1 parent 4573b07 commit 3c09376
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ public EnumRandomizer(final Class<E> enumeration, final E... excludedValues) thr
this.enumConstants = getFilteredList(enumeration, excludedValues);
}

/**
* Create a new {@link EnumRandomizer}.
*
* @param enumeration the enumeration from which this randomizer will generate random values
* @param seed the initial seed
* @param excludedValues the values to exclude from random picking
* @throws IllegalArgumentException when excludedValues contains all enumeration values,
* ie all elements from the enumeration are excluded
*/
public EnumRandomizer(final Class<E> enumeration, final long seed, final E... excludedValues) throws IllegalArgumentException {
super(seed);
checkExcludedValues(enumeration, excludedValues);
this.enumConstants = getFilteredList(enumeration, excludedValues);
}

/**
* Create a new {@link EnumRandomizer}.
*
Expand Down Expand Up @@ -110,6 +125,19 @@ public static <E extends Enum<E>> EnumRandomizer<E> aNewEnumRandomizer(final Cla
return new EnumRandomizer<>(enumeration, excludedValues);
}

/**
* Create a new {@link EnumRandomizer}.
*
* @param enumeration the enumeration from which this randomizer will generate random values
* @param seed the initial seed
* @param excludedValues the values to exclude from the subset in which the random value will be picked
* @param <E> the type of elements in the enumeration
* @return a new {@link EnumRandomizer}.
*/
public static <E extends Enum<E>> EnumRandomizer<E> aNewEnumRandomizer(final Class<E> enumeration, final long seed, final E... excludedValues) {
return new EnumRandomizer<>(enumeration, seed, excludedValues);
}

/**
* Get a random value within an enumeration or an enumeration subset (when values are excluded)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
package org.jeasy.random.randomizers.time;

import org.jeasy.random.api.Randomizer;
import org.jeasy.random.randomizers.misc.EnumRandomizer;
import org.jeasy.random.randomizers.range.IntegerRangeRandomizer;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.stream.Stream;

/**
* A {@link Randomizer} that generates random {@link Duration}.
Expand All @@ -39,13 +42,17 @@ public class DurationRandomizer implements Randomizer<Duration> {
private static final int MIN_AMOUNT = 0;
private static final int MAX_AMOUNT = 100;

private static final ChronoUnit[] excludedChronoUnits = chronoUnitsInvalidForDuration();

private final IntegerRangeRandomizer amountRandomizer;
private final EnumRandomizer<ChronoUnit> chronoUnitRandomizer;

/**
* Create a new {@link DurationRandomizer}.
*/
public DurationRandomizer() {
amountRandomizer = new IntegerRangeRandomizer(MIN_AMOUNT, MAX_AMOUNT);
chronoUnitRandomizer = new EnumRandomizer<>(ChronoUnit.class, excludedChronoUnits);
}

/**
Expand All @@ -55,6 +62,7 @@ public DurationRandomizer() {
*/
public DurationRandomizer(final long seed) {
amountRandomizer = new IntegerRangeRandomizer(MIN_AMOUNT, MAX_AMOUNT, seed);
chronoUnitRandomizer = new EnumRandomizer<>(ChronoUnit.class, seed, excludedChronoUnits);
}

/**
Expand All @@ -79,7 +87,19 @@ public static DurationRandomizer aNewDurationRandomizer(final long seed) {
@Override
public Duration getRandomValue() {
int randomAmount = amountRandomizer.getRandomValue();
return Duration.of(randomAmount, ChronoUnit.HOURS);
ChronoUnit unit = chronoUnitRandomizer.getRandomValue();
return Duration.of(randomAmount, unit);
}

/**
* Get an array of {@link ChronoUnit} that can't be used in {@link Duration#of(long, TemporalUnit)}.
*
* @return a new array of unsupported units.
*/
private static ChronoUnit[] chronoUnitsInvalidForDuration() {
return Stream.of(ChronoUnit.values())
.filter(unit -> unit != ChronoUnit.DAYS)
.filter(ChronoUnit::isDurationEstimated)
.toArray(ChronoUnit[]::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import static org.jeasy.random.randomizers.misc.EnumRandomizer.aNewEnumRandomizer;
import static org.jeasy.random.randomizers.misc.EnumRandomizerTest.Gender.FEMALE;
import static org.jeasy.random.randomizers.misc.EnumRandomizerTest.Gender.MALE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

Expand All @@ -44,6 +45,11 @@ void shouldAlwaysGenerateTheSameValueForTheSameSeed() {
assertThat(aNewEnumRandomizer(Gender.class, SEED).getRandomValue()).isEqualTo(FEMALE);
}

@Test
void shouldAlwaysGenerateTheSameValueForTheSameSeedWithExcludedValues() {
assertThat(aNewEnumRandomizer(Gender.class, SEED, FEMALE).getRandomValue()).isEqualTo(MALE);
}

public enum Gender {
MALE, FEMALE
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static org.jeasy.random.randomizers.time.ZoneOffsetRandomizer.aNewZoneOffsetRandomizer;
import static java.time.LocalDateTime.of;
import static java.time.ZoneOffset.ofTotalSeconds;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;

import java.sql.Time;
Expand All @@ -64,7 +65,10 @@
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Set;
import java.util.HashSet;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

Expand Down Expand Up @@ -113,7 +117,7 @@ static Object[][] generateSeededRandomizersAndTheirExpectedValues() {
expectedGregorianCalendar.setTimeInMillis(5106534569952410475L);

return new Object[][] {
{ aNewDurationRandomizer(SEED), Duration.of(72L, ChronoUnit.HOURS) },
{ aNewDurationRandomizer(SEED), Duration.of(72L, ChronoUnit.NANOS) },
{ aNewLocalDateRandomizer(SEED), LocalDate.of(2024, Month.MARCH, 20) },
{ aNewMonthDayRandomizer(SEED), MonthDay.of(Month.MARCH, 20) },
{ aNewLocalTimeRandomizer(SEED), LocalTime.of(16, 42, 58) },
Expand Down Expand Up @@ -142,4 +146,32 @@ void shouldGenerateTheSameValueForTheSameSeed(Randomizer<?> randomizer, Object e

then(actual).isEqualTo(expected);
}

@Test
void shouldGenerateDurationsWithRandomTemporalUnits() {
DurationRandomizer durationRandomizer = aNewDurationRandomizer(SEED);

Set<Duration> randomDurations = new HashSet<>();
for (int i = 0; i < 1000; i++) {
randomDurations.add(durationRandomizer.getRandomValue());
}

// there exists a non-zero duration which is less than a day
assertThat(randomDurations).anySatisfy(duration -> {
assertThat(duration).isNotEqualTo(Duration.ZERO);
assertThat(duration.toDays()).isEqualTo(0);
});

// there exists a non-zero duration which is less than an hour
assertThat(randomDurations).anySatisfy(duration -> {
assertThat(duration).isNotEqualTo(Duration.ZERO);
assertThat(duration.toHours()).isEqualTo(0);
});

// there exists a non-zero duration which is less than a minute
assertThat(randomDurations).anySatisfy(duration -> {
assertThat(duration).isNotEqualTo(Duration.ZERO);
assertThat(duration.toMinutes()).isEqualTo(0);
});
}
}

0 comments on commit 3c09376

Please sign in to comment.