github.com/leanovate/gopter@v0.2.9/gen/map_of.go (about) 1 package gen 2 3 import ( 4 "reflect" 5 6 "github.com/leanovate/gopter" 7 ) 8 9 // MapOf generates an arbitrary map of generated kay values. 10 // genParams.MaxSize sets an (exclusive) upper limit on the size of the map 11 // genParams.MinSize sets an (inclusive) lower limit on the size of the map 12 func MapOf(keyGen, elementGen gopter.Gen) gopter.Gen { 13 return func(genParams *gopter.GenParameters) *gopter.GenResult { 14 len := 0 15 if genParams.MaxSize > 0 || genParams.MinSize > 0 { 16 if genParams.MinSize > genParams.MaxSize { 17 panic("GenParameters.MinSize must be <= GenParameters.MaxSize") 18 } 19 20 if genParams.MaxSize == genParams.MinSize { 21 len = genParams.MaxSize 22 } else { 23 len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize 24 } 25 } 26 27 result, keySieve, keyShrinker, elementSieve, elementShrinker := genMap(keyGen, elementGen, genParams, len) 28 29 genResult := gopter.NewGenResult(result.Interface(), MapShrinker(keyShrinker, elementShrinker)) 30 if keySieve != nil || elementSieve != nil { 31 genResult.Sieve = forAllKeyValueSieve(keySieve, elementSieve) 32 } 33 return genResult 34 } 35 } 36 37 func genMap(keyGen, elementGen gopter.Gen, genParams *gopter.GenParameters, len int) (reflect.Value, func(interface{}) bool, gopter.Shrinker, func(interface{}) bool, gopter.Shrinker) { 38 element := elementGen(genParams) 39 elementSieve := element.Sieve 40 elementShrinker := element.Shrinker 41 42 key := keyGen(genParams) 43 keySieve := key.Sieve 44 keyShrinker := key.Shrinker 45 46 result := reflect.MakeMapWithSize(reflect.MapOf(key.ResultType, element.ResultType), len) 47 48 for i := 0; i < len; i++ { 49 keyValue, keyOk := key.Retrieve() 50 elementValue, elementOk := element.Retrieve() 51 52 if keyOk && elementOk { 53 if key == nil { 54 if elementValue == nil { 55 result.SetMapIndex(reflect.Zero(key.ResultType), reflect.Zero(element.ResultType)) 56 } else { 57 result.SetMapIndex(reflect.Zero(key.ResultType), reflect.ValueOf(elementValue)) 58 } 59 } else { 60 if elementValue == nil { 61 result.SetMapIndex(reflect.ValueOf(keyValue), reflect.Zero(element.ResultType)) 62 } else { 63 result.SetMapIndex(reflect.ValueOf(keyValue), reflect.ValueOf(elementValue)) 64 } 65 } 66 } 67 key = keyGen(genParams) 68 element = elementGen(genParams) 69 } 70 71 return result, keySieve, keyShrinker, elementSieve, elementShrinker 72 } 73 74 func forAllKeyValueSieve(keySieve, elementSieve func(interface{}) bool) func(interface{}) bool { 75 return func(v interface{}) bool { 76 rv := reflect.ValueOf(v) 77 for _, key := range rv.MapKeys() { 78 if keySieve != nil && !keySieve(key.Interface()) { 79 return false 80 } 81 if elementSieve != nil && !elementSieve(rv.MapIndex(key).Interface()) { 82 return false 83 } 84 } 85 return true 86 } 87 }