github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/internal/quick/quick.go (about) 1 package quick 2 3 import ( 4 "fmt" 5 "math" 6 "math/rand" 7 "reflect" 8 "strings" 9 ) 10 11 var DefaultConfig = Config{ 12 Sizes: []int{ 13 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 14 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 15 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 16 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 17 99, 100, 101, 18 127, 128, 129, 19 255, 256, 257, 20 1000, 1023, 1024, 1025, 21 2000, 2095, 2048, 2049, 22 4000, 4095, 4096, 4097, 23 }, 24 Seed: 0, 25 } 26 27 // Check is inspired by the standard quick.Check package, but enhances the 28 // API and tests arrays of larger sizes than the maximum of 50 hardcoded in 29 // testing/quick. 30 func Check(f interface{}) error { 31 return DefaultConfig.Check(f) 32 } 33 34 type Config struct { 35 Sizes []int 36 Seed int64 37 } 38 39 func (c *Config) Check(f interface{}) error { 40 v := reflect.ValueOf(f) 41 r := rand.New(rand.NewSource(c.Seed)) 42 t := v.Type().In(0) 43 44 makeValue := MakeValueFuncOf(t.Elem()) 45 makeArray := func(n int) reflect.Value { 46 array := reflect.MakeSlice(t, n, n) 47 for i := 0; i < n; i++ { 48 makeValue(array.Index(i), r) 49 } 50 return array 51 } 52 53 if makeArray == nil { 54 panic("cannot run quick check on function with input of type " + v.Type().In(0).String()) 55 } 56 57 for _, n := range c.Sizes { 58 for i := 0; i < 3; i++ { 59 in := makeArray(n) 60 ok := v.Call([]reflect.Value{in}) 61 if !ok[0].Bool() { 62 return fmt.Errorf("test #%d: failed on input of size %d: %#v\n", i+1, n, in.Interface()) 63 } 64 } 65 } 66 return nil 67 68 } 69 70 type MakeValueFunc func(reflect.Value, *rand.Rand) 71 72 func MakeValueFuncOf(t reflect.Type) MakeValueFunc { 73 switch t.Kind() { 74 case reflect.Bool: 75 return func(v reflect.Value, r *rand.Rand) { 76 v.SetBool((r.Int() % 2) != 0) 77 } 78 79 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 80 return func(v reflect.Value, r *rand.Rand) { 81 v.SetInt(r.Int63n(math.MaxInt32)) 82 } 83 84 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 85 return func(v reflect.Value, r *rand.Rand) { 86 v.SetUint(r.Uint64()) 87 } 88 89 case reflect.Float32, reflect.Float64: 90 return func(v reflect.Value, r *rand.Rand) { 91 v.SetFloat(r.Float64()) 92 } 93 94 case reflect.String: 95 return func(v reflect.Value, r *rand.Rand) { 96 const characters = "1234567890qwertyuiopasdfghjklzxcvbnm" 97 s := new(strings.Builder) 98 n := r.Intn(10) 99 for i := 0; i < n; i++ { 100 s.WriteByte(characters[i]) 101 } 102 v.SetString(s.String()) 103 } 104 105 case reflect.Array: 106 makeElem := MakeValueFuncOf(t.Elem()) 107 return func(v reflect.Value, r *rand.Rand) { 108 for i, n := 0, v.Len(); i < n; i++ { 109 makeElem(v.Index(i), r) 110 } 111 } 112 113 case reflect.Slice: 114 switch e := t.Elem(); e.Kind() { 115 case reflect.Uint8: 116 return func(v reflect.Value, r *rand.Rand) { 117 b := make([]byte, r.Intn(50)) 118 r.Read(b) 119 v.SetBytes(b) 120 } 121 default: 122 makeElem := MakeValueFuncOf(t.Elem()) 123 return func(v reflect.Value, r *rand.Rand) { 124 n := r.Intn(10) 125 s := reflect.MakeSlice(t, n, n) 126 for i := 0; i < n; i++ { 127 makeElem(s.Index(i), r) 128 } 129 v.Set(s) 130 } 131 } 132 133 case reflect.Map: 134 makeKey := MakeValueFuncOf(t.Key()) 135 makeElem := MakeValueFuncOf(t.Elem()) 136 return func(v reflect.Value, r *rand.Rand) { 137 m := reflect.MakeMap(t) 138 n := r.Intn(10) 139 k := reflect.New(t.Key()).Elem() 140 e := reflect.New(t.Elem()).Elem() 141 for i := 0; i < n; i++ { 142 makeKey(k, r) 143 makeElem(e, r) 144 m.SetMapIndex(k, e) 145 } 146 v.Set(m) 147 } 148 149 case reflect.Struct: 150 fields := make([]reflect.StructField, 0, t.NumField()) 151 makeValues := make([]MakeValueFunc, 0, cap(fields)) 152 for i, n := 0, cap(fields); i < n; i++ { 153 if f := t.Field(i); f.PkgPath == "" { // skip unexported fields 154 fields = append(fields, f) 155 makeValues = append(makeValues, MakeValueFuncOf(f.Type)) 156 } 157 } 158 return func(v reflect.Value, r *rand.Rand) { 159 for i := range fields { 160 makeValues[i](v.FieldByIndex(fields[i].Index), r) 161 } 162 } 163 164 case reflect.Ptr: 165 t = t.Elem() 166 makeValue := MakeValueFuncOf(t) 167 return func(v reflect.Value, r *rand.Rand) { 168 v.Set(reflect.New(t)) 169 makeValue(v.Elem(), r) 170 } 171 172 default: 173 panic("quick.Check does not support test values of type " + t.String()) 174 } 175 }