// 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) } }
// 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 } }
// Fail is a generator that always fails to generate a value // Useful as fallback func Fail(resultType reflect.Type) gopter.Gen { return func(*gopter.GenParameters) *gopter.GenResult { return gopter.NewEmptyResult(resultType) } }