1package gopter_test 2 3import ( 4 "reflect" 5 "testing" 6 7 "github.com/leanovate/gopter" 8) 9 10func constGen(value interface{}) gopter.Gen { 11 return func(*gopter.GenParameters) *gopter.GenResult { 12 return gopter.NewGenResult(value, gopter.NoShrinker) 13 } 14} 15 16func TestGenSample(t *testing.T) { 17 gen := constGen("sample") 18 19 value, ok := gen.Sample() 20 if !ok || value != "sample" { 21 t.Errorf("Invalid gen sample: %#v", value) 22 } 23} 24 25func BenchmarkMap(b *testing.B) { 26 for i := 0; i < b.N; i++ { 27 gen := constGen("sample") 28 var mappedWith string 29 mapper := func(v string) string { 30 mappedWith = v 31 return "other" 32 } 33 value, ok := gen.Map(mapper).Sample() 34 if !ok || value != "other" { 35 b.Errorf("Invalid gen sample: %#v", value) 36 } 37 if mappedWith != "sample" { 38 b.Errorf("Invalid mapped with: %#v", mappedWith) 39 } 40 41 gen = gen.SuchThat(func(interface{}) bool { 42 return false 43 }) 44 value, ok = gen.Map(mapper).Sample() 45 if ok { 46 b.Errorf("Invalid gen sample: %#v", value) 47 } 48 } 49} 50 51func TestGenMap(t *testing.T) { 52 gen := constGen("sample") 53 var mappedWith string 54 mapper := func(v string) string { 55 mappedWith = v 56 return "other" 57 } 58 value, ok := gen.Map(mapper).Sample() 59 if !ok || value != "other" { 60 t.Errorf("Invalid gen sample: %#v", value) 61 } 62 if mappedWith != "sample" { 63 t.Errorf("Invalid mapped with: %#v", mappedWith) 64 } 65 66 gen = gen.SuchThat(func(interface{}) bool { 67 return false 68 }) 69 value, ok = gen.Map(mapper).Sample() 70 if ok { 71 t.Errorf("Invalid gen sample: %#v", value) 72 } 73} 74 75func TestGenMapWithParams(t *testing.T) { 76 gen := constGen("sample") 77 var mappedWith string 78 var mappedWithParams *gopter.GenParameters 79 mapper := func(v string, params *gopter.GenParameters) string { 80 mappedWith = v 81 mappedWithParams = params 82 return "other" 83 } 84 value, ok := gen.Map(mapper).Sample() 85 if !ok || value != "other" { 86 t.Errorf("Invalid gen sample: %#v", value) 87 } 88 if mappedWith != "sample" { 89 t.Errorf("Invalid mapped with: %#v", mappedWith) 90 } 91 if mappedWithParams == nil || mappedWithParams.MaxSize != 100 { 92 t.Error("Mapper not called with currect parameters") 93 } 94 95 gen = gen.SuchThat(func(interface{}) bool { 96 return false 97 }) 98 value, ok = gen.Map(mapper).Sample() 99 if ok { 100 t.Errorf("Invalid gen sample: %#v", value) 101 } 102} 103 104func TestGenMapNoFunc(t *testing.T) { 105 defer expectPanic(t, "Param of Map has to be a func, but is string") 106 constGen("sample").Map("not a function") 107} 108 109func TestGenMapTooManyParams(t *testing.T) { 110 defer expectPanic(t, "Param of Map has to be a func with one or two params, but is 3") 111 constGen("sample").Map(func(a, b, C string) string { 112 return "" 113 }) 114} 115 116func TestGenMapInvalidSecondParam(t *testing.T) { 117 defer expectPanic(t, "Second parameter of mapper function has to be a *GenParameters") 118 constGen("sample").Map(func(a, b string) string { 119 return "" 120 }) 121} 122 123func TestGenMapToInvalidParamtype(t *testing.T) { 124 defer expectPanic(t, "Param of Map has to be a func with one param assignable to string, but is int") 125 constGen("sample").Map(func(a int) string { 126 return "" 127 }) 128} 129 130func TestGenMapToManyReturns(t *testing.T) { 131 defer expectPanic(t, "Param of Map has to be a func with one return value, but is 2") 132 constGen("sample").Map(func(a string) (string, bool) { 133 return "", false 134 }) 135} 136 137func TestGenMapResultIn(t *testing.T) { 138 gen := constGen("sample") 139 var mappedWith *gopter.GenResult 140 mapper := func(result *gopter.GenResult) string { 141 mappedWith = result 142 return "other" 143 } 144 145 value, ok := gen.Map(mapper).Sample() 146 if !ok || value != "other" { 147 t.Errorf("Invalid gen sample: %#v", value) 148 } 149 if mappedWith == nil { 150 t.Error("Mapper not called") 151 } 152 if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" { 153 t.Errorf("Mapper was called with invalid value: %#v", mapperValue) 154 } 155} 156 157func TestGenMapResultInWithParams(t *testing.T) { 158 gen := constGen("sample") 159 var mappedWith *gopter.GenResult 160 var mappedWithParams *gopter.GenParameters 161 mapper := func(result *gopter.GenResult, params *gopter.GenParameters) string { 162 mappedWith = result 163 mappedWithParams = params 164 return "other" 165 } 166 167 value, ok := gen.Map(mapper).Sample() 168 if !ok || value != "other" { 169 t.Errorf("Invalid gen sample: %#v", value) 170 } 171 if mappedWith == nil { 172 t.Error("Mapper not called") 173 } 174 if mappedWithParams == nil || mappedWithParams.MaxSize != 100 { 175 t.Error("Mapper not called with currect parameters") 176 } 177 if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" { 178 t.Errorf("Mapper was called with invalid value: %#v", mapperValue) 179 } 180} 181 182func TestGenMapResultOut(t *testing.T) { 183 gen := constGen("sample") 184 var mappedWith string 185 mapper := func(v string) *gopter.GenResult { 186 mappedWith = v 187 return gopter.NewGenResult("other", gopter.NoShrinker) 188 } 189 value, ok := gen.Map(mapper).Sample() 190 if !ok || value != "other" { 191 t.Errorf("Invalid gen sample: %#v", value) 192 } 193 if mappedWith != "sample" { 194 t.Errorf("Invalid mapped with: %#v", mappedWith) 195 } 196 197 gen = gen.SuchThat(func(interface{}) bool { 198 return false 199 }) 200 value, ok = gen.Map(mapper).Sample() 201 if ok { 202 t.Errorf("Invalid gen sample: %#v", value) 203 } 204} 205 206func TestGenMapResultInOut(t *testing.T) { 207 gen := constGen("sample") 208 var mappedWith *gopter.GenResult 209 mapper := func(result *gopter.GenResult) *gopter.GenResult { 210 mappedWith = result 211 return gopter.NewGenResult("other", gopter.NoShrinker) 212 } 213 214 value, ok := gen.Map(mapper).Sample() 215 if !ok || value != "other" { 216 t.Errorf("Invalid gen sample: %#v", value) 217 } 218 if mappedWith == nil { 219 t.Error("Mapper not called") 220 } 221 if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" { 222 t.Errorf("Mapper was called with invalid value: %#v", mapperValue) 223 } 224} 225 226func TestGenFlatMap(t *testing.T) { 227 gen := constGen("sample") 228 var mappedWith interface{} 229 mapper := func(v interface{}) gopter.Gen { 230 mappedWith = v 231 return constGen("other") 232 } 233 value, ok := gen.FlatMap(mapper, reflect.TypeOf("")).Sample() 234 if !ok || value != "other" { 235 t.Errorf("Invalid gen sample: %#v", value) 236 } 237 if mappedWith.(string) != "sample" { 238 t.Errorf("Invalid mapped with: %#v", mappedWith) 239 } 240 241 gen = gen.SuchThat(func(interface{}) bool { 242 return false 243 }) 244 value, ok = gen.FlatMap(mapper, reflect.TypeOf("")).Sample() 245 if ok { 246 t.Errorf("Invalid gen sample: %#v", value) 247 } 248} 249 250func TestGenMapResult(t *testing.T) { 251 gen := constGen("sample") 252 var mappedWith *gopter.GenResult 253 mapper := func(result *gopter.GenResult) *gopter.GenResult { 254 mappedWith = result 255 return gopter.NewGenResult("other", gopter.NoShrinker) 256 } 257 258 value, ok := gen.MapResult(mapper).Sample() 259 if !ok || value != "other" { 260 t.Errorf("Invalid gen sample: %#v", value) 261 } 262 if mappedWith == nil { 263 t.Error("Mapper not called") 264 } 265 if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" { 266 t.Errorf("Mapper was called with invalid value: %#v", mapperValue) 267 } 268} 269 270func TestCombineGens(t *testing.T) { 271 gens := make([]gopter.Gen, 0, 20) 272 for i := 0; i < 20; i++ { 273 gens = append(gens, constGen(i)) 274 } 275 gen := gopter.CombineGens(gens...) 276 raw, ok := gen.Sample() 277 if !ok { 278 t.Errorf("Invalid combined gen: %#v", raw) 279 } 280 values, ok := raw.([]interface{}) 281 if !ok || !reflect.DeepEqual(values, []interface{}{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) { 282 t.Errorf("Invalid combined gen: %#v", raw) 283 } 284 285 gens[0] = gens[0].SuchThat(func(interface{}) bool { 286 return false 287 }) 288 gen = gopter.CombineGens(gens...) 289 raw, ok = gen.Sample() 290 if ok { 291 t.Errorf("Invalid combined gen: %#v", raw) 292 } 293} 294 295func TestSuchThat(t *testing.T) { 296 var sieveArg string 297 sieve := func(v string) bool { 298 sieveArg = v 299 return true 300 } 301 gen := constGen("sample").SuchThat(sieve) 302 value, ok := gen.Sample() 303 if !ok || value != "sample" { 304 t.Errorf("Invalid result: %#v", value) 305 } 306 if sieveArg != "sample" { 307 t.Errorf("Invalid sieveArg: %#v", sieveArg) 308 } 309 310 sieveArg = "" 311 var sieve2Arg string 312 sieve2 := func(v string) bool { 313 sieve2Arg = v 314 return false 315 } 316 gen = gen.SuchThat(sieve2) 317 _, ok = gen.Sample() 318 if ok { 319 t.Error("Did not expect a result") 320 } 321 if sieveArg != "sample" { 322 t.Errorf("Invalid sieveArg: %#v", sieveArg) 323 } 324 if sieve2Arg != "sample" { 325 t.Errorf("Invalid sieve2Arg: %#v", sieve2Arg) 326 } 327} 328 329func TestGenSuchThatNoFunc(t *testing.T) { 330 defer expectPanic(t, "Param of SuchThat has to be a func, but is string") 331 constGen("sample").SuchThat("not a function") 332} 333 334func TestGenSuchTooManyParams(t *testing.T) { 335 defer expectPanic(t, "Param of SuchThat has to be a func with one param, but is 2") 336 constGen("sample").SuchThat(func(a, b string) bool { 337 return false 338 }) 339} 340 341func TestGenSuchThatToInvalidParamtype(t *testing.T) { 342 defer expectPanic(t, "Param of SuchThat has to be a func with one param assignable to string, but is int") 343 constGen("sample").SuchThat(func(a int) bool { 344 return false 345 }) 346} 347 348func TestGenSuchToManyReturns(t *testing.T) { 349 defer expectPanic(t, "Param of SuchThat has to be a func with one return value, but is 2") 350 constGen("sample").SuchThat(func(a string) (string, bool) { 351 return "", false 352 }) 353} 354 355func TestGenSuchToInvalidReturns(t *testing.T) { 356 defer expectPanic(t, "Param of SuchThat has to be a func with one return value of bool, but is string") 357 constGen("sample").SuchThat(func(a string) string { 358 return "" 359 }) 360} 361 362func TestWithShrinker(t *testing.T) { 363 var shrinkerArg interface{} 364 shrinker := func(v interface{}) gopter.Shrink { 365 shrinkerArg = v 366 return gopter.NoShrink 367 } 368 gen := constGen("sample").WithShrinker(shrinker) 369 result := gen(gopter.DefaultGenParameters()) 370 value, ok := result.Retrieve() 371 if !ok { 372 t.Errorf("Invalid combined value: %#v", value) 373 } 374 result.Shrinker(value) 375 if shrinkerArg != "sample" { 376 t.Errorf("Invalid shrinkerArg: %#v", shrinkerArg) 377 } 378} 379 380func expectPanic(t *testing.T, expected string) { 381 r := recover() 382 if r == nil { 383 t.Errorf("The code did not panic") 384 } else if r.(string) != expected { 385 t.Errorf("Panic does not match: '%#v' != '%#v'", r, expected) 386 } 387} 388