All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.sirwellington.alchemy.generator.NumberGenerators Maven / Gradle / Ivy

Go to download

Part of the Alchemy collection. More Data means better tests. Alchemy Generator makes it easier to test your code by providing generators for common Objects and Data.

There is a newer version: 2.5.0
Show newest version
/*
 * Copyright 2015 SirWellington Tech.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package tech.sirwellington.alchemy.generator;

import java.util.List;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.sirwellington.alchemy.annotations.access.Internal;
import tech.sirwellington.alchemy.annotations.access.NonInstantiable;
import tech.sirwellington.alchemy.annotations.designs.patterns.StrategyPattern;

import static tech.sirwellington.alchemy.annotations.designs.patterns.StrategyPattern.Role.CONCRETE_BEHAVIOR;
import static tech.sirwellington.alchemy.generator.BooleanGenerators.booleans;
import static tech.sirwellington.alchemy.generator.Checks.checkNotNull;
import static tech.sirwellington.alchemy.generator.Checks.checkThat;

/**
 * Common {@linkplain AlchemyGenerator Generators} for NumberGenerators.
 * 
* Includes: *
*
 * + Integers
 * + Longs
 * + Doubles
 * 
* * @author SirWellington */ @NonInstantiable @StrategyPattern(role = CONCRETE_BEHAVIOR) public final class NumberGenerators { private final static Logger LOG = LoggerFactory.getLogger(NumberGenerators.class); NumberGenerators() throws IllegalAccessException { throw new IllegalAccessException("cannot instantiate this class"); } /** * Creates a series of integer values. * * @param inclusiveLowerBound The inclusive lower bound * @param exclusiveUpperBound The exclusive upper bound * * @return * * @throws IllegalArgumentException If {@code lowerBound >= upperBound} */ public static AlchemyGenerator integers(int inclusiveLowerBound, int exclusiveUpperBound) throws IllegalArgumentException { checkThat(inclusiveLowerBound < exclusiveUpperBound, "Lower Bound must be < Upper Bound"); final boolean isNegativeLowerBound = inclusiveLowerBound < 0; // <= because of the fact that 0 would be the *exclusive* upper bound. final boolean isNegativeUpperBound = exclusiveUpperBound <= 0; return () -> { if (isNegativeLowerBound && isNegativeUpperBound) { int min = (-exclusiveUpperBound); int max = inclusiveLowerBound == Integer.MIN_VALUE ? Integer.MAX_VALUE : -inclusiveLowerBound; //Adjust by one, for inclusivity int minAdjustedForInclusivity = safeIncrement(min); int maxAdjustedForInclusivity = safeIncrement(max); int value = RandomUtils.nextInt(minAdjustedForInclusivity, maxAdjustedForInclusivity); return -value; } else if (isNegativeLowerBound) { boolean shouldProduceNegative = booleans().get(); if (shouldProduceNegative) { int max = inclusiveLowerBound == Integer.MIN_VALUE ? Integer.MAX_VALUE : -inclusiveLowerBound; int maxAdjustedForInclusivity = safeIncrement(max); return -RandomUtils.nextInt(0, maxAdjustedForInclusivity); } else { return RandomUtils.nextInt(0, exclusiveUpperBound); } } else //Positive bounds { return RandomUtils.nextInt(inclusiveLowerBound, exclusiveUpperBound); } }; } /** * Creates a series of positive integer values from 1 to Integer.MAX_VALUE * * @return * @see #smallPositiveIntegers() * @see #positiveLongs() */ public static AlchemyGenerator positiveIntegers() { return integers(1, Integer.MAX_VALUE); } /** * Creates a series of small positive integers from 1 to 1000. * * @return * @see #positiveIntegers() */ public static AlchemyGenerator smallPositiveIntegers() { return integers(1, 1000); } /** * Creates a series of negative integer values from Integer.MIN_VALUE to -1 * * @return */ public static AlchemyGenerator negativeIntegers() { return () -> { int value = positiveIntegers().get(); return value < 0 ? value : -value; }; } /** * Produces long values within the specified Range * * @param inclusiveLowerBound inclusive lower bound * @param exclusiveUpperBound exclusive upper bound * * @return * * @throws IllegalArgumentException If {@code lowerBound >= upperBound} */ public static AlchemyGenerator longs(long inclusiveLowerBound, long exclusiveUpperBound) throws IllegalArgumentException { checkThat(inclusiveLowerBound < exclusiveUpperBound, "Lower Bound must be < Upper Bound"); final boolean negativeLowerBound = inclusiveLowerBound < 0; // <= because of the fact that 0 would be the *exclusive* upper bound. final boolean negativeUpperBound = exclusiveUpperBound <= 0; return () -> { if (negativeLowerBound && negativeUpperBound) { //Reverse the min and max long min = (-exclusiveUpperBound); long max = inclusiveLowerBound == Long.MIN_VALUE ? Long.MAX_VALUE : -inclusiveLowerBound; //Adjust by one, for inclusivity long minAdjustedForInclusivity = safeIncrement(min); long maxAdjustedForInclusivity = safeIncrement(max); long value = RandomUtils.nextLong(minAdjustedForInclusivity, maxAdjustedForInclusivity); return -value; } else if (negativeLowerBound) { boolean shouldProduceNegative = booleans().get(); if (shouldProduceNegative) { long min = 0L; long max = inclusiveLowerBound == Long.MIN_VALUE ? Long.MAX_VALUE : -inclusiveLowerBound; long maxAdjustedForInclusivity = safeIncrement(max); long value = -RandomUtils.nextLong(min, maxAdjustedForInclusivity); return value; } else { return RandomUtils.nextLong(0, exclusiveUpperBound); } } else //Positive bounds { return RandomUtils.nextLong(inclusiveLowerBound, exclusiveUpperBound); } }; } /** * Produces a series of positive values from {@code 1} to {@code Long.MAX_VALUE} * * @return * @see #smallPositiveLongs() * @see #positiveIntegers() */ public static AlchemyGenerator positiveLongs() { return longs(1L, Long.MAX_VALUE); } /** * Produces a series of positive values from 1 to 10,000 * * @return * * @see #positiveLongs() * @see #positiveLongs() */ public static AlchemyGenerator smallPositiveLongs() { return longs(1L, 10_000L); } /** * Creates a series of double values within the specified range * * @param inclusiveLowerBound The inclusive lower bound * @param inclusiveUpperBound The inclusive upper bound * * @return * * @throws IllegalArgumentException If {@code lowerBound >= upperBound} */ public static AlchemyGenerator doubles(double inclusiveLowerBound, double inclusiveUpperBound) throws IllegalArgumentException { checkThat(inclusiveLowerBound <= inclusiveUpperBound, "Upper Bound must be greater than Lower Bound"); final boolean negativeLowerBound = inclusiveLowerBound < 0; final boolean negativeUpperBound = inclusiveUpperBound < 0; return () -> { if (negativeLowerBound && negativeUpperBound) { return -RandomUtils.nextDouble(-inclusiveUpperBound, -inclusiveLowerBound); } else if (negativeLowerBound) { boolean shouldProduceNegative = booleans().get(); if (shouldProduceNegative) { return -RandomUtils.nextDouble(0, -inclusiveLowerBound); } else { return RandomUtils.nextDouble(0, inclusiveUpperBound); } } else //Positive bounds { return RandomUtils.nextDouble(inclusiveLowerBound, inclusiveUpperBound); } }; } /** * Creates a series of positive double values from 0 to Double.MAX_VALUE. * * @return * @see #smallPositiveDoubles() * @see #positiveIntegers() */ public static AlchemyGenerator positiveDoubles() { return doubles(0.1, Double.MAX_VALUE); } /** * Creates a series of positive doubles from 0.1 to 1000.0 * * @return * * @see #positiveDoubles() * @see #positiveIntegers() */ public static AlchemyGenerator smallPositiveDoubles() { return doubles(0.1, 1000); } /** * Generates an integer value from the specified set. * * @param values * * @return */ public static AlchemyGenerator integersFromFixedList(List values) { checkNotNull(values); checkThat(!values.isEmpty(), "No values specified"); return () -> { int index = integers(0, values.size()).get(); return values.get(index); }; } /** * Generates a double value from the specified set. * * @param values * * @return */ public static AlchemyGenerator doublesFromFixedList(List values) { checkNotNull(values); checkThat(!values.isEmpty(), "No values specified"); return () -> { int index = integers(0, values.size()).get(); return values.get(index); }; } //============================================================================================== //Internal //============================================================================================== /** * Attempts to increment the value without potentially circling back to {@link Long#MIN_VALUE} * * @param value * * @return */ @Internal static long safeIncrement(long value) { return value == Long.MAX_VALUE ? value : value + 1; } /** * Attempts to decrement the value without potentially circling back to {@link Long#MAX_VALUE}. * * @param value * * @return */ @Internal static long safeDecrement(long value) { return value == Long.MIN_VALUE ? value : value - 1; } /** * Attempts to increment the value without potentially circling back to * {@link Integer#MIN_VALUE} * * @param value * @return */ @Internal static int safeIncrement(int value) { return value == Integer.MAX_VALUE ? value : value + 1; } /** * Attempts to decrement the value without potentially circling back to * {@link Integer#MAX_VALUE}. * * @param value * @return */ @Internal static int safeDecrement(int value) { return value == Integer.MIN_VALUE ? value : value - 1; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy