/*
* Licensed to the author under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 net.java.quickcheck.generator;
import static java.util.Arrays.*;
import static java.util.concurrent.TimeUnit.*;
import static net.java.quickcheck.generator.CombinedGenerators.*;
import static net.java.quickcheck.generator.support.CharacterGenerator.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
import net.java.quickcheck.ExtendibleGenerator;
import net.java.quickcheck.Generator;
import net.java.quickcheck.ObjectGenerator;
import net.java.quickcheck.generator.distribution.Distribution;
import net.java.quickcheck.generator.support.ByteGenerator;
import net.java.quickcheck.generator.support.CharacterGenerator;
import net.java.quickcheck.generator.support.CloningGenerator;
import net.java.quickcheck.generator.support.DateGenerator;
import net.java.quickcheck.generator.support.DoubleGenerator;
import net.java.quickcheck.generator.support.FixedValuesGenerator;
import net.java.quickcheck.generator.support.IntegerGenerator;
import net.java.quickcheck.generator.support.LongGenerator;
import net.java.quickcheck.generator.support.ObjectDefaultMappingGenerator;
import net.java.quickcheck.generator.support.ObjectGeneratorImpl;
import net.java.quickcheck.generator.support.StringGenerator;
import net.java.quickcheck.srcgenerator.Iterables;
import net.java.quickcheck.srcgenerator.Samples;
/**
* <p>
* {@link PrimitiveGenerators} contains factory methods for primitive value
* generators. These can be used to build custom test case generators.
* <p/>
* <p>
* The default distribution for generators is {@link Distribution#UNIFORM}.
* </p>
*/
@Samples
@Iterables
public class PrimitiveGenerators {
public static final int DEFAULT_STRING_MAX_LENGTH = StringGenerator.MAX_LENGTH;
/**
* Create a new string generator.<br>
*
* The characters are from the Basic Latin and Latin-1 Supplement unicode blocks.
*/
public static ExtendibleGenerator<Character, String> strings() {
return new StringGenerator();
}
/**
* Create a new string generator which generates strings of characters
* ranging from lo to hi.
*
* @param lo
* lower boundary character
* @param hi
* upper boundary character
*/
public static ExtendibleGenerator<Character, String> strings(char lo,
char hi) {
return new StringGenerator(lo, hi);
}
/**
* Create a new string generator which generates strings of characters from
* the given string.
*/
public static ExtendibleGenerator<Character, String> strings(
String allowedCharacters) {
return new StringGenerator(characters(allowedCharacters));
}
/**
* Create a new string generator which generates strings of characters from
* the given string with a length between min and max.
*/
public static ExtendibleGenerator<Character, String> strings(String allowedCharacters, int min, int max) {
return new StringGenerator(new IntegerGenerator(min, max), characters(allowedCharacters));
}
/**
* Creates a new String genearator which generates strings whose length
* ranges from zero to given length.
*/
public static ExtendibleGenerator<Character, String> strings(int max) {
return strings(0, max);
}
/**
* Create a new string generator which generates strings of sizes ranging
* from loLength to hiLength.
*
* @param min
* lower size boundary
* @param max
* upper size boundary
*/
public static ExtendibleGenerator<Character, String> strings(int min, int max) {
return new StringGenerator(new IntegerGenerator(min, max), new CharacterGenerator());
}
/**
* Create a new string generator which creates strings of characters
* generated by the given character generator with a length generated by the
* length generator.
*
*/
public static ExtendibleGenerator<Character, String> strings(
Generator<Integer> length, Generator<Character> characters) {
return new StringGenerator(length, characters);
}
/**
* Create a new string generator which creates strings of characters
* generated by the given character generator.
*
*/
public static ExtendibleGenerator<Character, String> strings(
Generator<Character> characterGenerator) {
return new StringGenerator(characterGenerator);
}
/**
* Create a new string generator which creates strings of characters from
* a-z and A-Z.
*/
public static ExtendibleGenerator<Character, String> letterStrings() {
return new StringGenerator(characters('a', 'z')).add(characters('A', 'Z'));
}
/**
* Create a new string generator which creates strings with sizes ranging
* from loLengh to hiLength of characters from a-z and A-Z.
*/
public static ExtendibleGenerator<Character, String> letterStrings(int min, int max) {
StringGenerator generator = new StringGenerator(new IntegerGenerator(min, max), characters('a', 'z'));
return generator.add(characters('A', 'Z'));
}
/**
* Create a new string generator which creates strings of characters
* generated by {@link PrimitiveGenerators#basicLatinCharacters()} and
* {@link PrimitiveGenerators#latin1SupplementCharacters()}.
*/
public static ExtendibleGenerator<Character, String> printableStrings() {
return new StringGenerator(basicLatinCharacters()).add(latin1SupplementCharacters());
}
/**
* Create a new string generator for strings that are not empty.
*/
public static ExtendibleGenerator<Character, String> nonEmptyStrings() {
return strings(1, StringGenerator.MAX_LENGTH);
}
/**
* Create a new character generator which generates characters ranging from
* lo to hi.
*/
public static Generator<Character> characters(char lo, char hi) {
return new CharacterGenerator(lo, hi);
}
/**
* Create a new character generator.<br>
*
* The characters are from the Basic Latin and Latin-1 Supplement unicode blocks.
*/
public static Generator<Character> characters(){
return new CharacterGenerator();
}
/**
* Create a new character generator which generates characters from the
* given character array.
*/
public static Generator<Character> characters(Character... chars) {
return characters(asList(chars));
}
/**
* Create a new character generator which generates characters from the
* given string.
*/
public static Generator<Character> characters(String string) {
Character[] chars = new Character[string.length()];
for(int i = 0; i < chars.length; i++) chars[i] = string.charAt(i);
return characters(chars);
}
/**
* Create a new character generator which generates characters from the
* given character collection.
*/
public static Generator<Character> characters(Collection<Character> chars) {
return new FixedValuesGenerator<Character>(chars);
}
/**
* Create a new character generator which generates latin-1 supplement
* characters.
*/
public static Generator<Character> latin1SupplementCharacters() {
return characters(LATIN_1_SUPPLEMENT.getFirst(), LATIN_1_SUPPLEMENT.getSecond());
}
/**
* Create a new character generator which generates latin characters.
*/
public static Generator<Character> basicLatinCharacters() {
return characters(BASIC_LATIN.getFirst(), BASIC_LATIN.getSecond());
}
/**
* Create a new integer generator which creates integers ranging from
* {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}.
*
*/
public static Generator<Integer> integers() {
return new IntegerGenerator();
}
/**
* Create a new integer generator which creates integers that are at equal
* or greater than low.
*/
public static Generator<Integer> integers(int low) {
return new IntegerGenerator(low, Integer.MAX_VALUE);
}
/**
* Create a new integer generator which creates integers ranging from lo to
* hi.
*/
public static Generator<Integer> integers(int lo, int hi) {
return new IntegerGenerator(lo, hi);
}
/**
* Create a new integer generator which creates integers ranging from lo to
* hi based on the given {@link Distribution}.
*/
public static Generator<Integer> integers(int lo, int hi,
Distribution distribution) {
return new IntegerGenerator(lo, hi, distribution);
}
/**
* Create a new integer generator which creates positive integers.
*/
public static Generator<Integer> positiveIntegers() {
return positiveIntegers(Integer.MAX_VALUE);
}
/**
* Create a new integer generator which creates positive integers than are
* equal or smaller than high.
*/
public static Generator<Integer> positiveIntegers(int high) {
return new IntegerGenerator(1, high);
}
/**
* Create a new byte generator which creates byte values ranging from
* {@link Byte#MIN_VALUE} to {@link Byte#MAX_VALUE}.
*
*/
public static Generator<Byte> bytes() {
return new ByteGenerator();
}
/**
* Create a new byte generator which creates byte values ranging from lo to
* hi.
*/
public static Generator<Byte> bytes(byte lo, byte hi) {
return new ByteGenerator(lo, hi);
}
/**
* Create a new integer generator which creates integers ranging from lo to
* hi based on the given {@link Distribution}.
*/
public static Generator<Byte> bytes(byte lo, byte hi,
Distribution distribution) {
return new ByteGenerator(lo, hi, distribution);
}
/**
* Create a new long generator which creates longs ranging from
* {@link Long#MIN_VALUE} to {@link Long#MAX_VALUE}.
*/
public static Generator<Long> longs() {
return new LongGenerator();
}
/**
* Create a new long generator which creates longs ranging from lo to hi.
*/
public static Generator<Long> longs(long lo, long hi) {
return new LongGenerator(lo, hi, Distribution.UNIFORM);
}
/**
* Create a new long generator which creates longs ranging from lo to hi
* based on the given {@link Distribution}.
*/
public static Generator<Long> longs(long lo, long hi,
Distribution distribution) {
return new LongGenerator(lo, hi, distribution);
}
/**
* Create a new long generator which creates long values ranging from 1 to
* {@link Long#MAX_VALUE}.
*/
public static Generator<Long> positiveLongs() {
return positiveLongs(Long.MAX_VALUE);
}
/**
* Create a new long generator which creates long values ranging from 1 to
* hi.
*/
public static Generator<Long> positiveLongs(long hi) {
return longs(1, hi);
}
/**
* Create a new double generator which creates doubles ranging from
* {@link Double#MIN_VALUE} to {@link Double#MAX_VALUE}.
*/
public static Generator<Double> doubles() {
return new DoubleGenerator();
}
/**
* Create a new double generator which creates doubles ranging from lo to
* hi.
*/
public static Generator<Double> doubles(double lo, double hi) {
return new DoubleGenerator(lo, hi);
}
/**
* Create a new double generator which creates doubles ranging from lo to hi
* based on the given {@link Distribution}.
*/
public static Generator<Double> doubles(double lo, double hi,
Distribution distribution) {
return new DoubleGenerator(lo, hi, distribution);
}
/**
* Create a generator for boolean values.
*/
public static Generator<Boolean> booleans() {
return new FixedValuesGenerator<Boolean>(Arrays.asList(Boolean.TRUE, Boolean.FALSE));
}
/**
* Create a generator for null values.
*/
public static <T> Generator<T> nulls() {
return new FixedValuesGenerator<T>();
}
/**
* Create a generator for date values.
*/
public static Generator<Date> dates() {
return dates(MILLISECONDS);
}
/**
* Create a generator for date values with the given precision.
*/
public static Generator<Date> dates(TimeUnit precision) {
return dates(Long.MIN_VALUE, Long.MAX_VALUE, precision);
}
/**
* Create a generator for date values from low to high.
*/
public static Generator<Date> dates(Date low, Date high) {
return dates(low.getTime(), high.getTime());
}
/**
* Create a generator for date values from low to high.
*/
public static Generator<Date> dates(long low, long high) {
return dates(low, high, MILLISECONDS);
}
/**
* Create a generator for date values from low to high with the given
* precision.
*/
public static Generator<Date> dates(Long low, Long high, TimeUnit precision) {
return new DateGenerator(precision, low, high, DEFAULT_MAX_TRIES);
}
/**
* Create a generator for fixed value generator.
*/
public static <T> Generator<T> fixedValues(T value) {
return new FixedValuesGenerator<T>(value);
}
/**
* Create a fixed value generator returning one of the values from the
* values array.
*/
public static <T> Generator<T> fixedValues(T... values) {
return fixedValues(Arrays.asList(values));
}
/**
* Create a fixed value generator returning one of the values from the
* values collection.
*/
public static <T> Generator<T> fixedValues(Collection<T> values) {
return new FixedValuesGenerator<T>(values);
}
/**
* A cloning generator which uses object serialization to create clones of
* the prototype object. For each call a new copy of the prototype will be
* generated.
*/
public static <T> Generator<T> clonedValues(T prototype) {
return new CloningGenerator<T>(prototype);
}
/**
* Create a generator of enumeration values.
*
* @param <T>
* Type of enumerations
* @param enumClass
* class of enumeration
* @return generator of enum values
*/
public static <T extends Enum<T>> Generator<T> enumValues(Class<T> enumClass) {
return enumValues(enumClass, Collections.<T> emptyList());
}
/**
* Create a generator of enumeration values.
*
* @param <T>
* Type of enumerations
* @param enumClass
* class of enumeration
* @param excluded
* excluded values of enumeration
* @return generator of enum values
*/
public static <T extends Enum<T>> Generator<T> enumValues(
Class<T> enumClass, T... excluded) {
return enumValues(enumClass, Arrays.asList(excluded));
}
/**
* Create a generator of enumeration values.
*
* @param <T>
* Type of enumerations
* @param enumClass
* class of enumeration
* @param excludedCollection
* excluded values of enumeration
* @return generator of enum values
*/
public static <T extends Enum<T>> Generator<T> enumValues(
Class<T> enumClass, Collection<T> excludedCollection) {
EnumSet<T> excluded = EnumSet.noneOf(enumClass);
excluded.addAll(excludedCollection);
return new FixedValuesGenerator<T>(EnumSet.complementOf(excluded));
}
/**
* Create a generator for {@link Object java.lang.Object} instances.
* <p>
* Note: every invocation of {@link Generator#next()} creates a new instance.
* </p>
*/
public static Generator<Object> objects(){
return new net.java.quickcheck.generator.support.ObjectGenerator();
}
/**
* Create a generator from a {@link ObjectGenerator declarative object generator definition}.
*/
public static <T> ObjectGenerator<T> objects(Class<T> objectType) {
return new ObjectGeneratorImpl<T>(objectType);
}
/**
* Create a generator from a {@link ObjectGenerator declarative object generator definition}.<br/>
*
* Default values will be used for all {@link ObjectGenerator#on(Object) undefined methods}.
*/
public static <T> ObjectGenerator<T> defaultObjects(Class<T> objectType) {
return new ObjectDefaultMappingGenerator<T>(objectType);
}
}