// StructPtr generates pointers to a given struct type. // rt has to be the reflect type of the struct, gens contains a map of field generators. // Note that the result types of the generators in gen have to match the type of the correspoinding // field in the struct. Also note that only public fields of a struct can be generated func StructPtr(rt reflect.Type, gens map[string]gopter.Gen) gopter.Gen { if rt.Kind() == reflect.Ptr { rt = rt.Elem() } if rt.Kind() != reflect.Struct { return Fail(rt) } return func(genParams *gopter.GenParameters) *gopter.GenResult { result := reflect.New(rt) for name, gen := range gens { field, ok := rt.FieldByName(name) if !ok { continue } value, ok := gen(genParams).Retrieve() if !ok { return gopter.NewEmptyResult(rt) } result.Elem().FieldByIndex(field.Index).Set(reflect.ValueOf(value)) } return gopter.NewGenResult(result.Interface(), gopter.NoShrinker) } }
// Time generates an arbitrary time.Time func Time() gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { sec := genParams.NextInt64() usec := genParams.NextInt64() return gopter.NewGenResult(time.Unix(sec, usec), TimeShrinker) } }
// UInt64Range generates uint64 numbers within a given range func UInt64Range(min, max uint64) gopter.Gen { if max < min { return Fail(reflect.TypeOf(uint64(0))) } d := max - min + 1 if d == 0 { // Check overflow (i.e. max = MaxInt64, min = MinInt64) return func(genParams *gopter.GenParameters) *gopter.GenResult { return gopter.NewGenResult(genParams.NextUint64(), UInt64Shrinker) } } return func(genParams *gopter.GenParameters) *gopter.GenResult { genResult := gopter.NewGenResult(min+genParams.NextUint64()%d, UInt64Shrinker) genResult.Sieve = func(v interface{}) bool { return v.(uint64) >= min && v.(uint64) <= max } return genResult } }
// OneConstOf generate one of a list of constant values func OneConstOf(consts ...interface{}) gopter.Gen { if len(consts) == 0 { return Fail(reflect.TypeOf(nil)) } return func(genParams *gopter.GenParameters) *gopter.GenResult { idx := genParams.Rng.Intn(len(consts)) return gopter.NewGenResult(consts[idx], gopter.NoShrinker) } }
// Int64Range generates int64 numbers within a given range func Int64Range(min, max int64) gopter.Gen { if max < min { return Fail(reflect.TypeOf(int64(0))) } if max == math.MaxInt64 && min == math.MinInt64 { // Check for range overflow return func(genParams *gopter.GenParameters) *gopter.GenResult { return gopter.NewGenResult(genParams.NextInt64(), Int64Shrinker) } } rangeSize := uint64(max - min + 1) return func(genParams *gopter.GenParameters) *gopter.GenResult { var nextResult uint64 = uint64(min) + (genParams.NextUint64() % rangeSize) genResult := gopter.NewGenResult(int64(nextResult), Int64Shrinker) genResult.Sieve = func(v interface{}) bool { return v.(int64) >= min && v.(int64) <= max } return genResult } }
// Float32Range generates float32 numbers within a given range func Float32Range(min, max float32) gopter.Gen { d := max - min if d < 0 || d > math.MaxFloat32 { return Fail(reflect.TypeOf(float32(0))) } return func(genParams *gopter.GenParameters) *gopter.GenResult { genResult := gopter.NewGenResult(min+genParams.Rng.Float32()*d, Float32Shrinker) genResult.Sieve = func(v interface{}) bool { return v.(float32) >= min && v.(float32) <= max } return genResult } }
// SliceOf generates an arbitrary slice of generated elements func SliceOf(elementGen gopter.Gen) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { len := 0 if genParams.Size > 0 { len = genParams.Rng.Intn(genParams.Size) } result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len) genResult := gopter.NewGenResult(result.Interface(), SliceShrinker(elementShrinker)) if elementSieve != nil { genResult.Sieve = forAllSieve(elementSieve) } return genResult } }
// SliceOfN generates a slice of generated elements with definied length func SliceOfN(len int, elementGen gopter.Gen) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len) genResult := gopter.NewGenResult(result.Interface(), SliceShrinkerOne(elementShrinker)) if elementSieve != nil { genResult.Sieve = func(v interface{}) bool { rv := reflect.ValueOf(v) return rv.Len() == len && forAllSieve(elementSieve)(v) } } else { genResult.Sieve = func(v interface{}) bool { return reflect.ValueOf(v).Len() == len } } return genResult } }
// PtrOf generates a pointer to a generated element func PtrOf(elementGen gopter.Gen) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { element := elementGen(genParams) elementShrinker := element.Shrinker elementSieve := element.Sieve value, ok := element.Retrieve() if !ok || genParams.NextBool() { result := gopter.NewEmptyResult(reflect.PtrTo(element.ResultType)) result.Sieve = func(v interface{}) bool { return v == nil || elementSieve == nil || elementSieve(reflect.ValueOf(v).Elem().Interface()) } return result } // To get the right pointer type we have to create a slice with one element slice := reflect.MakeSlice(reflect.SliceOf(element.ResultType), 0, 1) slice = reflect.Append(slice, reflect.ValueOf(value)) result := gopter.NewGenResult(slice.Index(0).Addr().Interface(), PtrShrinker(elementShrinker)) result.Sieve = func(v interface{}) bool { return v == nil || elementSieve == nil || elementSieve(reflect.ValueOf(v).Elem().Interface()) } return result } }
// Const creates a generator for a constant value // Not the most exciting generator, but can be helpful from time to time func Const(value interface{}) gopter.Gen { return func(*gopter.GenParameters) *gopter.GenResult { return gopter.NewGenResult(value, gopter.NoShrinker) } }
// TimeRange generates an arbitrary time.Time with a range // from defines the start of the time range // duration defines the overall duration of the time range func TimeRange(from time.Time, duration time.Duration) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { v := from.Add(time.Duration(genParams.Rng.Int63n(int64(duration)))) return gopter.NewGenResult(v, TimeShrinker) } }
// Bool generates an arbitrary bool value func Bool() gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { return gopter.NewGenResult(genParams.NextBool(), gopter.NoShrinker) } }
func counterGen(start int) gopter.Gen { return func(*gopter.GenParameters) *gopter.GenResult { start++ return gopter.NewGenResult(start, gopter.NoShrinker) } }