github.com/leanovate/gopter@v0.2.9/gen/slice_of.go (about) 1 package gen 2 3 import ( 4 "reflect" 5 6 "github.com/leanovate/gopter" 7 ) 8 9 // SliceOf generates an arbitrary slice of generated elements 10 // genParams.MaxSize sets an (exclusive) upper limit on the size of the slice 11 // genParams.MinSize sets an (inclusive) lower limit on the size of the slice 12 func SliceOf(elementGen gopter.Gen, typeOverrides ...reflect.Type) gopter.Gen { 13 var typeOverride reflect.Type 14 if len(typeOverrides) > 1 { 15 panic("too many type overrides specified, at most 1 may be provided.") 16 } else if len(typeOverrides) == 1 { 17 typeOverride = typeOverrides[0] 18 } 19 return func(genParams *gopter.GenParameters) *gopter.GenResult { 20 len := 0 21 if genParams.MaxSize > 0 || genParams.MinSize > 0 { 22 if genParams.MinSize > genParams.MaxSize { 23 panic("GenParameters.MinSize must be <= GenParameters.MaxSize") 24 } 25 26 if genParams.MaxSize == genParams.MinSize { 27 len = genParams.MaxSize 28 } else { 29 len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize 30 } 31 } 32 result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len, typeOverride) 33 34 genResult := gopter.NewGenResult(result.Interface(), SliceShrinker(elementShrinker)) 35 if elementSieve != nil { 36 genResult.Sieve = forAllSieve(elementSieve) 37 } 38 return genResult 39 } 40 } 41 42 // SliceOfN generates a slice of generated elements with definied length 43 func SliceOfN(desiredlen int, elementGen gopter.Gen, typeOverrides ...reflect.Type) gopter.Gen { 44 var typeOverride reflect.Type 45 if len(typeOverrides) > 1 { 46 panic("too many type overrides specified, at most 1 may be provided.") 47 } else if len(typeOverrides) == 1 { 48 typeOverride = typeOverrides[0] 49 } 50 return func(genParams *gopter.GenParameters) *gopter.GenResult { 51 result, elementSieve, elementShrinker := genSlice(elementGen, genParams, desiredlen, typeOverride) 52 53 genResult := gopter.NewGenResult(result.Interface(), SliceShrinkerOne(elementShrinker)) 54 if elementSieve != nil { 55 genResult.Sieve = func(v interface{}) bool { 56 rv := reflect.ValueOf(v) 57 return rv.Len() == desiredlen && forAllSieve(elementSieve)(v) 58 } 59 } else { 60 genResult.Sieve = func(v interface{}) bool { 61 return reflect.ValueOf(v).Len() == desiredlen 62 } 63 } 64 return genResult 65 } 66 } 67 68 func genSlice(elementGen gopter.Gen, genParams *gopter.GenParameters, desiredlen int, typeOverride reflect.Type) (reflect.Value, func(interface{}) bool, gopter.Shrinker) { 69 element := elementGen(genParams) 70 elementSieve := element.Sieve 71 elementShrinker := element.Shrinker 72 73 sliceType := typeOverride 74 if sliceType == nil { 75 sliceType = element.ResultType 76 } 77 78 result := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, desiredlen) 79 80 for i := 0; i < desiredlen; i++ { 81 value, ok := element.Retrieve() 82 83 if ok { 84 if value == nil { 85 result = reflect.Append(result, reflect.Zero(sliceType)) 86 } else { 87 result = reflect.Append(result, reflect.ValueOf(value)) 88 } 89 } 90 element = elementGen(genParams) 91 } 92 93 return result, elementSieve, elementShrinker 94 } 95 96 func forAllSieve(elementSieve func(interface{}) bool) func(interface{}) bool { 97 return func(v interface{}) bool { 98 rv := reflect.ValueOf(v) 99 for i := rv.Len() - 1; i >= 0; i-- { 100 if !elementSieve(rv.Index(i).Interface()) { 101 return false 102 } 103 } 104 return true 105 } 106 }